commit 7bbe26d72edb5c2f64aac77dbd437c6e7c6080cd
parent dbf3f42140ee5c0a5c00656697e45c397a49c9bf
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 23 Sep 2025 16:47:28 +0200
switch to 32-byte nonces, fixes #10450
Diffstat:
9 files changed, 132 insertions(+), 120 deletions(-)
diff --git a/src/donau/donau-httpd_batch-submit.c b/src/donau/donau-httpd_batch-submit.c
@@ -154,8 +154,9 @@ DH_handler_submit_receipts_post (struct DH_RequestContext *rc,
/* Check nonce unique*/
for (size_t j = i + 1; j < num_dr; j++)
{
- if (irc.donation_receipts[i].nonce.value ==
- irc.donation_receipts[j].nonce.value)
+ if (0 ==
+ GNUNET_memcmp (&irc.donation_receipts[i].nonce,
+ &irc.donation_receipts[j].nonce))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Donation receipt nonce is not unique!\n");
diff --git a/src/donau/test_donau_httpd.conf b/src/donau/test_donau_httpd.conf
@@ -10,7 +10,7 @@ CURRENCY_ROUND_UNIT = EUR:0.01
SERVE = tcp
# Base url of the Donau
-DOMAIN = "Bern"
+LEGAL_DOMAIN = "Bern"
BASE_URL = "http://localhost:8080/"
# Directory with our terms of service.
@@ -57,8 +57,8 @@ IDLE_RESERVE_EXPIRATION_TIME = 4 weeks
[donaudb-postgres]
CONFIG = "postgres:///donaucheck"
-# Coins for the tests.
-[coin_eur_ct_1_rsa]
+# Docos for the tests.
+[doco_eur_ct_1_rsa]
value = EUR:0.01
duration_withdraw = 1 year
duration_spend = 2 years
@@ -70,7 +70,7 @@ fee_refund = EUR:0.01
CIPHER = RSA
rsa_keysize = 1024
-[coin_eur_ct_1_cs]
+[doco_eur_ct_1_cs]
value = EUR:0.01
duration_withdraw = 1 year
duration_spend = 2 years
@@ -81,7 +81,7 @@ fee_refresh = EUR:0.01
fee_refund = EUR:0.01
CIPHER = CS
-[coin_eur_ct_10_rsa]
+[doco_eur_ct_10_rsa]
value = EUR:0.10
duration_withdraw = 1 year
duration_spend = 2 years
@@ -93,7 +93,7 @@ fee_refund = EUR:0.01
CIPHER = RSA
rsa_keysize = 1024
-[coin_eur_ct_10_cs]
+[doco_eur_ct_10_cs]
value = EUR:0.10
duration_withdraw = 1 year
duration_spend = 2 years
@@ -104,7 +104,7 @@ fee_refresh = EUR:0.03
fee_refund = EUR:0.01
CIPHER = CS
-[coin_eur_1_rsa]
+[doco_eur_1_rsa]
value = EUR:1
duration_withdraw = 1 year
duration_spend = 2 years
@@ -116,7 +116,7 @@ fee_refund = EUR:0.01
CIPHER = RSA
rsa_keysize = 1024
-[coin_eur_1_cs]
+[doco_eur_1_cs]
value = EUR:1
duration_withdraw = 1 year
duration_spend = 2 years
diff --git a/src/donaudb/0002-donau_receipts_submitted.sql b/src/donaudb/0002-donau_receipts_submitted.sql
@@ -17,7 +17,7 @@
CREATE TABLE receipts_submitted
(receipt_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,h_tax_number BYTEA NOT NULL
- ,nonce INT4 NOT NULL UNIQUE
+ ,nonce BYTEA NOT NULL UNIQUE CHECK (LENGTH(nonce)=32)
,h_donation_unit_pub BYTEA NOT NULL REFERENCES donation_units (h_donation_unit_pub)
,donation_unit_sig BYTEA NOT NULL UNIQUE
,donation_year INT8 NOT NULL
diff --git a/src/donaudb/donau_do_insert_submitted_receipts.sql b/src/donaudb/donau_do_insert_submitted_receipts.sql
@@ -13,10 +13,12 @@
-- You should have received a copy of the GNU General Public License along with
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
--
-CREATE OR REPLACE FUNCTION do_insert_submitted_receipts(
+
+DROP FUNCTION IF EXISTS do_insert_submitted_receipts;
+CREATE FUNCTION do_insert_submitted_receipts(
IN in_h_tax_number BYTEA,
IN ina_h_donation_unit_pubs BYTEA[],
- IN ina_nonces INT4[],
+ IN ina_nonces BYTEA[],
IN ina_donation_unit_sigs BYTEA[],
IN in_donation_year INT8,
--
@@ -26,7 +28,7 @@ LANGUAGE plpgsql
AS $$
DECLARE
i INT4;
- ini_nonce INT4;
+ ini_nonce BYTEA;
ini_h_donation_unit_pub BYTEA;
ini_donation_unit_sig BYTEA;
BEGIN
diff --git a/src/donaudb/pg_insert_submitted_receipts.c b/src/donaudb/pg_insert_submitted_receipts.c
@@ -27,6 +27,7 @@
#include "donau_service.h"
#include "donau_pq_lib.h"
+
enum GNUNET_DB_QueryStatus
DH_PG_insert_submitted_receipts (
void *cls,
@@ -37,16 +38,16 @@ DH_PG_insert_submitted_receipts (
{
struct PostgresClosure *pg = cls;
struct GNUNET_HashCode h_donation_unit_pubs[GNUNET_NZL (num_dr)];
- uint32_t nonces[GNUNET_NZL (num_dr)];
+ struct DONAU_UniqueDonorIdentifierNonce nonces[GNUNET_NZL (num_dr)];
struct DONAU_DonationUnitSignature donation_unit_sigs[GNUNET_NZL (num_dr)];
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (h_donor_tax_id),
GNUNET_PQ_query_param_array_auto_from_type (num_dr,
h_donation_unit_pubs,
pg->conn),
- GNUNET_PQ_query_param_array_uint32 (num_dr,
- nonces,
- pg->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (num_dr,
+ nonces,
+ pg->conn),
DONAU_PQ_query_param_array_donation_unit_sig (num_dr,
donation_unit_sigs,
pg->conn),
@@ -68,20 +69,18 @@ DH_PG_insert_submitted_receipts (
const struct DONAU_DonationReceipt *dr = &donation_receipts[i];
h_donation_unit_pubs[i] = dr->h_donation_unit_pub.hash;
- nonces[i] = dr->nonce.value;
+ nonces[i] = dr->nonce;
donation_unit_sigs[i] = dr->donation_unit_sig;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Do insert submitted receipt\n");
}
-
PREPARE (pg,
"call_insert_submitted_receipts",
"SELECT "
" out_conflict AS conflicted"
" FROM do_insert_submitted_receipts"
"($1,$2,$3,$4,$5);");
-
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_insert_submitted_receipts",
params,
diff --git a/src/include/donau_crypto_lib.h b/src/include/donau_crypto_lib.h
@@ -186,7 +186,7 @@ struct DONAU_UniqueDonorIdentifierNonce
/**
* Actual nonce value.
*/
- uint32_t value;
+ uint32_t value[32 / 4];
};
/**
@@ -252,7 +252,7 @@ struct DONAU_BearerToken
/**
* The token of variable length.
*/
- char *token;
+ const char *token;
};
diff --git a/src/testing/test_donau_api.conf b/src/testing/test_donau_api.conf
@@ -17,7 +17,7 @@ TERMS_ETAG = tos
PRIVACY_ETAG = 0
PORT = 8080
DB = postgres
-DOMAIN = "Bern"
+LEGAL_DOMAIN = "Bern"
BASE_URL = "http://localhost:8080/"
SERVE = tcp
EXPIRE_LEGAL = 5
@@ -53,4 +53,3 @@ KEY_DIR = ${PWD}/test_donau_api_home/exchange-secmod-eddsa/keys
OVERLAP_DURATION = 0
SM_PRIV_KEY = ${DONAU_RUNTIME_DIR}donau-secmod-eddsa/secmod-private-key
UNIXPATH = ${DONAU_RUNTIME_DIR}donau-secmod-eddsa/server.sock
-
diff --git a/src/testing/testing_api_cmd_issue_receipts.c b/src/testing/testing_api_cmd_issue_receipts.c
@@ -54,7 +54,7 @@ struct StatusState
unsigned int expected_response_code;
/**
- */
+ */
bool uses_cs;
/**
@@ -190,43 +190,46 @@ issue_receipts_status_cb (void *cls,
TALER_TESTING_interpreter_fail (ss->is);
return;
}
- struct DONAU_BlindedDonationUnitSignature *blinded_sigs =
- biresp->details.ok.blinded_sigs;
- for (size_t i = 0; i < ss->num_bkp; i++)
{
- GNUNET_assert (GNUNET_OK ==
- DONAU_donation_unit_sig_unblind (
- &ss->receipts[i].donation_unit_sig,
- &blinded_sigs[i],
- &ss->blinding_secrets[i],
- &ss->h_udis[i],
- ss->alg_values[i],
- &ss->selected_pks[i]));
-
- /* check udi message */
- struct DONAU_UniqueDonorIdentifierHashP checkudi_hash;
- DONAU_unique_donor_id_hash (
- &ss->h_donor_tax_id,
- &ss->receipts[i].nonce,
- &checkudi_hash);
- GNUNET_assert (0 == GNUNET_CRYPTO_hash_cmp (&checkudi_hash.hash,
- &ss->h_udis[i].hash));
- /* check signature */
- if (GNUNET_OK != DONAU_donation_receipt_verify (
- &ss->selected_pks[i],
- &checkudi_hash,
- &ss->receipts[i].donation_unit_sig))
- {
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Donation receipt signature invalid!\n");
- }
- else
+ struct DONAU_BlindedDonationUnitSignature *blinded_sigs =
+ biresp->details.ok.blinded_sigs;
+ for (size_t i = 0; i < ss->num_bkp; i++)
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "!!!!!Donation receipt signature valid!\n");
- }
+ struct DONAU_UniqueDonorIdentifierHashP checkudi_hash;
+ GNUNET_assert (GNUNET_OK ==
+ DONAU_donation_unit_sig_unblind (
+ &ss->receipts[i].donation_unit_sig,
+ &blinded_sigs[i],
+ &ss->blinding_secrets[i],
+ &ss->h_udis[i],
+ ss->alg_values[i],
+ &ss->selected_pks[i]));
+
+ /* check udi message */
+ DONAU_unique_donor_id_hash (
+ &ss->h_donor_tax_id,
+ &ss->receipts[i].nonce,
+ &checkudi_hash);
+ GNUNET_assert (0 == GNUNET_CRYPTO_hash_cmp (&checkudi_hash.hash,
+ &ss->h_udis[i].hash));
+ /* check signature */
+ if (GNUNET_OK !=
+ DONAU_donation_receipt_verify (
+ &ss->selected_pks[i],
+ &checkudi_hash,
+ &ss->receipts[i].donation_unit_sig))
+ {
+ GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Donation receipt signature invalid!\n");
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Donation receipt signature valid!\n");
+ }
+ }
}
TALER_TESTING_interpreter_next (ss->is);
}
@@ -285,41 +288,43 @@ cs_stage_two_callback (
return;
}
- struct DONAU_DonationUnitPublicKey *cs_pk =
- &csr_data->ss->keys->donation_unit_keys[csr_data->position].key;
- struct DONAU_BatchIssueValues *alg_values = GNUNET_new (struct
- DONAU_BatchIssueValues);
- struct DONAU_BudiMasterSecretP ps;
- struct DONAU_UniqueDonorIdentifierHashP *udi_hash =
- &csr_data->ss->h_udis[csr_data->position];
- union GNUNET_CRYPTO_BlindingSecretP *blinding_secret =
- &csr_data->ss->blinding_secrets[csr_data->position];
- struct DONAU_UniqueDonorIdentifierNonce *udi_nonce =
- &csr_data->ss->receipts[csr_data->position].nonce;
-
- GNUNET_assert (GNUNET_CRYPTO_BSA_CS == cs_pk->bsign_pub_key->cipher);
-
- DONAU_donation_unit_ewv_copy (alg_values,
- &csrresp->details.ok.
- alg_values);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
- &ps,
- sizeof (ps));
- DONAU_budi_secret_create (&ps,
- alg_values,
- blinding_secret);
- GNUNET_assert (GNUNET_OK ==
- DONAU_donation_unit_blind (
- cs_pk,
- blinding_secret,
- &csr_data->nonce, /* nonce only needed for cs */
- udi_nonce,
- &csr_data->ss->h_donor_tax_id,
- alg_values,
- udi_hash,
- blinded_udi));
- csr_data->ss->alg_values[csr_data->position] = alg_values;
- csr_data->ss->cs_pending--;
+ {
+ struct DONAU_DonationUnitPublicKey *cs_pk =
+ &csr_data->ss->keys->donation_unit_keys[csr_data->position].key;
+ struct DONAU_BatchIssueValues *alg_values = GNUNET_new (struct
+ DONAU_BatchIssueValues);
+ struct DONAU_BudiMasterSecretP ps;
+ struct DONAU_UniqueDonorIdentifierHashP *udi_hash =
+ &csr_data->ss->h_udis[csr_data->position];
+ union GNUNET_CRYPTO_BlindingSecretP *blinding_secret =
+ &csr_data->ss->blinding_secrets[csr_data->position];
+ struct DONAU_UniqueDonorIdentifierNonce *udi_nonce =
+ &csr_data->ss->receipts[csr_data->position].nonce;
+
+ GNUNET_assert (GNUNET_CRYPTO_BSA_CS == cs_pk->bsign_pub_key->cipher);
+
+ DONAU_donation_unit_ewv_copy (alg_values,
+ &csrresp->details.ok.
+ alg_values);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
+ &ps,
+ sizeof (ps));
+ DONAU_budi_secret_create (&ps,
+ alg_values,
+ blinding_secret);
+ GNUNET_assert (GNUNET_OK ==
+ DONAU_donation_unit_blind (
+ cs_pk,
+ blinding_secret,
+ &csr_data->nonce, /* nonce only needed for cs */
+ udi_nonce,
+ &csr_data->ss->h_donor_tax_id,
+ alg_values,
+ udi_hash,
+ blinded_udi));
+ csr_data->ss->alg_values[csr_data->position] = alg_values;
+ csr_data->ss->cs_pending--;
+ }
if (0 == csr_data->ss->cs_pending)
phase_two (csr_data->ss);
}
@@ -423,16 +428,18 @@ status_run (void *cls,
GNUNET_new_array (ss->num_bkp, struct DONAU_UniqueDonorIdentifierHashP);
for (size_t cnt = 0; cnt < ss->num_bkp; cnt++)
{
+ struct DONAU_UniqueDonorIdentifierNonce *udi_nonce
+ = &ss->receipts[cnt].nonce;
+ struct DONAU_BlindedUniqueDonorIdentifier *blinded_udi
+ = &ss->bkps[cnt].blinded_udi;
+ struct DONAU_UniqueDonorIdentifierHashP *udi_hash
+ = &ss->h_udis[cnt];
+ struct DONAU_BudiMasterSecretP ps;
+ const struct DONAU_BatchIssueValues *alg_values;
+
DONAU_donation_unit_pub_hash (&ss->selected_pks[cnt],
&ss->bkps[cnt].h_donation_unit_pub);
ss->receipts[cnt].h_donation_unit_pub = ss->bkps[cnt].h_donation_unit_pub;
- struct DONAU_UniqueDonorIdentifierNonce *udi_nonce =
- &ss->receipts[cnt].nonce;
- struct DONAU_BudiMasterSecretP ps;
- const struct DONAU_BatchIssueValues *alg_values;
- struct DONAU_BlindedUniqueDonorIdentifier *blinded_udi =
- &ss->bkps[cnt].blinded_udi;
- struct DONAU_UniqueDonorIdentifierHashP *udi_hash = &ss->h_udis[cnt];
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
&ps,
sizeof (ps));
@@ -459,25 +466,28 @@ status_run (void *cls,
ss->alg_values[cnt] = alg_values;
break;
case GNUNET_CRYPTO_BSA_CS:
- struct CSR_Data *csr_data = GNUNET_new (struct CSR_Data);
- TALER_cs_withdraw_nonce_derive ( // FIXME: write new method
- (struct TALER_PlanchetMasterSecretP *) &ps,
- &csr_data->nonce.cs_nonce);
- csr_data->ss = ss;
- csr_data->position = cnt;
- csr_data->csr_handle = DONAU_csr_issue (
- TALER_TESTING_interpreter_get_context (is),
- TALER_TESTING_get_donau_url (is),
- &ss->selected_pks[cnt],
- &csr_data->nonce.cs_nonce,
- &cs_stage_two_callback,
- csr_data);
- if (NULL == csr_data->csr_handle)
{
- GNUNET_break (0);
+ struct CSR_Data *csr_data = GNUNET_new (struct CSR_Data);
+
+ TALER_cs_withdraw_nonce_derive ( // FIXME: write new method
+ (struct TALER_PlanchetMasterSecretP *) &ps,
+ &csr_data->nonce.cs_nonce);
+ csr_data->ss = ss;
+ csr_data->position = cnt;
+ csr_data->csr_handle = DONAU_csr_issue (
+ TALER_TESTING_interpreter_get_context (is),
+ TALER_TESTING_get_donau_url (is),
+ &ss->selected_pks[cnt],
+ &csr_data->nonce.cs_nonce,
+ &cs_stage_two_callback,
+ csr_data);
+ if (NULL == csr_data->csr_handle)
+ {
+ GNUNET_break (0);
+ }
+ ss->cs_pending++;
+ break;
}
- ss->cs_pending++;
- break;
default:
GNUNET_break (0);
}
diff --git a/src/util/donau-secmod-cs.c b/src/util/donau-secmod-cs.c
@@ -207,7 +207,8 @@ main (int argc,
{
struct TALER_SECMOD_Options opts = {
.max_workers = 16,
- .section = "donau"
+ .section = "donau",
+ .cprefix = "doco_"
};
struct GNUNET_GETOPT_CommandLineOption options[] = {
TALER_SECMOD_OPTIONS (&opts),