From 94a5359494bcc24916c9f7f8323ace4643bc0065 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 12 Feb 2022 00:52:19 +0100 Subject: -address misc. fixmes --- src/auditor/taler-helper-auditor-reserves.c | 22 ++-- src/exchange/taler-exchange-httpd_withdraw.c | 65 +++++----- src/include/taler_crypto_lib.h | 72 ++++++----- src/include/taler_signatures.h | 8 +- src/lib/exchange_api_common.c | 35 +++--- src/lib/exchange_api_refreshes_reveal.c | 9 +- src/lib/exchange_api_withdraw2.c | 36 +++--- src/util/crypto.c | 142 ---------------------- src/util/denom.c | 175 +++++++++++++++++++++------ src/util/taler-exchange-secmod-cs.c | 6 +- src/util/test_crypto.c | 34 +++++- src/util/wallet_signatures.c | 48 ++++++++ 12 files changed, 342 insertions(+), 310 deletions(-) diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c index 610193187..e9cd51d8c 100644 --- a/src/auditor/taler-helper-auditor-reserves.c +++ b/src/auditor/taler-helper-auditor-reserves.c @@ -508,12 +508,7 @@ handle_reserve_out (void *cls, struct GNUNET_TIME_Timestamp valid_start; struct GNUNET_TIME_Timestamp expire_withdraw; enum GNUNET_DB_QueryStatus qs; - struct TALER_WithdrawRequestPS wsrd = { - .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW), - .purpose.size = htonl (sizeof (wsrd)), - .reserve_pub = *reserve_pub, - .h_coin_envelope = *h_blind_ev - }; + struct TALER_DenominationHash h_denom_pub; /* should be monotonically increasing */ GNUNET_assert (rowid >= ppr.last_reserve_out_serial_id); @@ -523,7 +518,7 @@ handle_reserve_out (void *cls, initializes wsrd.h_denomination_pub! */ qs = TALER_ARL_get_denomination_info (denom_pub, &issue, - &wsrd.h_denomination_pub); + &h_denom_pub); if (0 > qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -569,17 +564,16 @@ handle_reserve_out (void *cls, GNUNET_JSON_pack_data_auto ("reserve_pub", reserve_pub), GNUNET_JSON_pack_data_auto ("denompub_h", - &wsrd.h_denomination_pub))); + &h_denom_pub))); } /* check reserve_sig (first: setup remaining members of wsrd) */ - TALER_amount_hton (&wsrd.amount_with_fee, - amount_with_fee); if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, - &wsrd, - &reserve_sig->eddsa_signature, - &reserve_pub->eddsa_pub)) + TALER_wallet_withdraw_verify (&h_denom_pub, + amount_with_fee, + h_blind_ev, + reserve_pub, + reserve_sig)) { TALER_ARL_report (report_bad_sig_losses, GNUNET_JSON_PACK ( diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c index 8e4bbb475..8598f1322 100644 --- a/src/exchange/taler-exchange-httpd_withdraw.c +++ b/src/exchange/taler-exchange-httpd_withdraw.c @@ -90,10 +90,21 @@ reply_withdraw_insufficient_funds ( */ struct WithdrawContext { + /** - * Details about the withdrawal request. + * Hash of the (blinded) message to be signed by the Exchange. */ - struct TALER_WithdrawRequestPS wsrd; + struct TALER_BlindedCoinHash h_coin_envelope; + + /** + * Value of the coin being exchanged (matching the denomination key) + * plus the transaction fee. We include this in what is being + * signed so that we can verify a reserve's remaining total balance + * without needing to access the respective denomination key + * information each time. + */ + struct TALER_Amount amount_with_fee; + /** * Blinded planchet. @@ -143,8 +154,6 @@ withdraw_transaction (void *cls, uint64_t ruuid; now = GNUNET_TIME_timestamp_get (); - wc->collectable.reserve_pub = wc->wsrd.reserve_pub; - wc->collectable.h_coin_envelope = wc->wsrd.h_coin_envelope; qs = TEH_plugin->do_withdraw (TEH_plugin->cls, &wc->collectable, now, @@ -173,7 +182,6 @@ withdraw_transaction (void *cls, { struct TALER_EXCHANGEDB_ReserveHistory *rh; struct TALER_Amount balance; - struct TALER_Amount requested_amount; TEH_plugin->rollback (TEH_plugin->cls); // FIXME: maybe start read-committed here? @@ -192,7 +200,7 @@ withdraw_transaction (void *cls, /* The reserve does not have the required amount (actual * amount + withdraw fee) */ qs = TEH_plugin->get_reserve_history (TEH_plugin->cls, - &wc->wsrd.reserve_pub, + &wc->collectable.reserve_pub, &balance, &rh); if (NULL == rh) @@ -204,12 +212,11 @@ withdraw_transaction (void *cls, "reserve history"); return GNUNET_DB_STATUS_HARD_ERROR; } - TALER_amount_ntoh (&requested_amount, - &wc->wsrd.amount_with_fee); - *mhd_ret = reply_withdraw_insufficient_funds (connection, - &balance, - &requested_amount, - rh); + *mhd_ret = reply_withdraw_insufficient_funds ( + connection, + &balance, + &wc->collectable.amount_with_fee, + rh); TEH_plugin->free_reserve_history (TEH_plugin->cls, rh); return GNUNET_DB_STATUS_HARD_ERROR; @@ -287,7 +294,7 @@ check_request_idempotent (struct TEH_RequestContext *rc, enum GNUNET_DB_QueryStatus qs; qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls, - &wc->wsrd.h_coin_envelope, + &wc->collectable.h_coin_envelope, &wc->collectable); if (0 > qs) { @@ -336,8 +343,8 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, if (GNUNET_OK != GNUNET_STRINGS_string_to_data (args[0], strlen (args[0]), - &wc.wsrd.reserve_pub, - sizeof (wc.wsrd.reserve_pub))) + &wc.collectable.reserve_pub, + sizeof (wc.collectable.reserve_pub))) { GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, @@ -460,21 +467,11 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW, NULL); } - TALER_amount_hton (&wc.wsrd.amount_with_fee, - &wc.collectable.amount_with_fee); - - // FIXME: move this logic into libtalerutil! - /* verify signature! */ - wc.wsrd.purpose.size - = htonl (sizeof (wc.wsrd)); - wc.wsrd.purpose.purpose - = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW); - wc.wsrd.h_denomination_pub - = wc.collectable.denom_pub_hash; + if (GNUNET_OK != TALER_coin_ev_hash (&wc.blinded_planchet, &wc.collectable.denom_pub_hash, - &wc.wsrd.h_coin_envelope)) + &wc.collectable.h_coin_envelope)) { GNUNET_break (0); GNUNET_JSON_parse_free (spec); @@ -483,15 +480,15 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, NULL); } + if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify ( - TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, - &wc.wsrd, - &wc.collectable.reserve_sig.eddsa_signature, - &wc.wsrd.reserve_pub.eddsa_pub)) + TALER_wallet_withdraw_verify (&wc.collectable.denom_pub_hash, + &wc.collectable.amount_with_fee, + &wc.collectable.h_coin_envelope, + &wc.collectable.reserve_pub, + &wc.collectable.reserve_sig)) { - TALER_LOG_WARNING ( - "Client supplied invalid signature for withdraw request\n"); + GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_FORBIDDEN, diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 5e531d90c..6f64de2ea 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -857,9 +857,6 @@ struct TALER_BlindedCsPlanchet /** * Public nonce. - * FIXME: this nonce being here has created TONS - * of trouble. Likely split off from this data - * structure in the future! */ struct TALER_CsNonce nonce; }; @@ -1085,31 +1082,12 @@ void TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); -/** - * @brief Function for CS signatures to derive public R_0 and R_1 - * - * @param nonce withdraw nonce from a client - * @param denom_priv denomination privkey as long-term secret - * @param r_pub the resulting R_0 and R_1 - * @return enum GNUNET_GenericReturnValue - */ -enum GNUNET_GenericReturnValue -TALER_denom_cs_derive_r_public ( - const struct TALER_CsNonce *nonce, - const struct TALER_DenominationPrivateKey *denom_priv, - struct TALER_DenominationCSPublicRPairP *r_pub); - - /** * Blind coin for blind signing with @a dk using blinding secret @a coin_bks. * - * NOTE/FIXME: As a particular oddity, the @a blinded_planchet - * is only partially initialized by this function in the - * case of CS-denominations. Here, the 'nonce' must - * be initialized separately! This has been a MAJOR - * source of bugs, and points to a likely need for a - * reorganization of either that data structure or - * this function! + * NOTE: As a particular oddity, the @a blinded_planchet is only partially + * initialized by this function in the case of CS-denominations. Here, the + * 'nonce' must be initialized separately! * * @param dk denomination public key to blind for * @param coin_bks blinding secret to use @@ -1564,8 +1542,8 @@ TALER_planchet_blinding_secret_create ( * @param coin_priv coin private key * @param[out] c_hash set to the hash of the public key of the coin (needed later) * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and - * other withdraw operations, pd->blinded_planchet.cipher will be set - * to cipher from dk + * other withdraw operations, `pd->blinded_planchet.cipher` will be set + * to cipher from @a dk * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue @@ -1574,8 +1552,7 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, const union TALER_DenominationBlindingKeyP *bks, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinPubHash *c_hash, - struct TALER_PlanchetDetail *pd - ); + struct TALER_PlanchetDetail *pd); /** @@ -2316,6 +2293,43 @@ TALER_wallet_link_verify ( const struct TALER_CoinSpendSignatureP *coin_sig); +/** + * Sign withdraw request. + * + * @param h_denom_pub hash of the denomiantion public key of the coin to withdraw + * @param amount_with_fee amount to debit the reserve for + * @param bch blinded coin hash + * @param reserve_priv private key to sign with + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_withdraw_sign ( + const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHash *bch, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify withdraw request. + * + * @param h_denom_pub hash of the denomiantion public key of the coin to withdraw + * @param amount_with_fee amount to debit the reserve for + * @param bch blinded coin hash + * @param reserve_pub public key of the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_withdraw_verify ( + const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHash *bch, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + /** * Verify recoup signature. * diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 3c31a4b60..037955096 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -440,13 +440,7 @@ struct TALER_WithdrawRequestPS struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * Reserve public key (which reserve to withdraw from). This is - * the public key which must match the signature. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Value of the coin being exchangeed (matching the denomination key) + * Value of the coin being exchanged (matching the denomination key) * plus the transaction fee. We include this in what is being * signed so that we can verify a reserve's remaining total balance * without needing to access the respective denomination key diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 399eb280a..53a75a934 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -124,7 +124,8 @@ TALER_EXCHANGE_parse_reserve_history ( "WITHDRAW")) { struct TALER_ReserveSignatureP sig; - struct TALER_WithdrawRequestPS withdraw_purpose; + struct TALER_DenominationHash h_denom_pub; + struct TALER_BlindedCoinHash bch; struct TALER_Amount withdraw_fee; struct GNUNET_JSON_Specification withdraw_spec[] = { GNUNET_JSON_spec_fixed_auto ("reserve_sig", @@ -132,9 +133,9 @@ TALER_EXCHANGE_parse_reserve_history ( TALER_JSON_spec_amount_any ("withdraw_fee", &withdraw_fee), GNUNET_JSON_spec_fixed_auto ("h_denom_pub", - &withdraw_purpose.h_denomination_pub), + &h_denom_pub), GNUNET_JSON_spec_fixed_auto ("h_coin_envelope", - &withdraw_purpose.h_coin_envelope), + &bch), GNUNET_JSON_spec_end () }; @@ -147,19 +148,14 @@ TALER_EXCHANGE_parse_reserve_history ( GNUNET_break_op (0); return GNUNET_SYSERR; } - withdraw_purpose.purpose.size - = htonl (sizeof (withdraw_purpose)); - withdraw_purpose.purpose.purpose - = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW); - withdraw_purpose.reserve_pub = *reserve_pub; - TALER_amount_hton (&withdraw_purpose.amount_with_fee, - &amount); + /* Check that the signature is a valid withdraw request */ if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, - &withdraw_purpose, - &sig.eddsa_signature, - &reserve_pub->eddsa_pub)) + TALER_wallet_withdraw_verify (&h_denom_pub, + &amount, + &bch, + reserve_pub, + &sig)) { GNUNET_break_op (0); GNUNET_JSON_parse_free (withdraw_spec); @@ -172,8 +168,7 @@ TALER_EXCHANGE_parse_reserve_history ( key_state = TALER_EXCHANGE_get_keys (exchange); dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, - &withdraw_purpose. - h_denomination_pub); + &h_denom_pub); if ( (GNUNET_YES != TALER_amount_cmp_currency (&withdraw_fee, &dki->fee_withdraw)) || @@ -193,10 +188,10 @@ TALER_EXCHANGE_parse_reserve_history ( /* Check check that the same withdraw transaction isn't listed twice by the exchange. We use the "uuid" array to remember the hashes of all - purposes, and compare the hashes to find - duplicates. */// - GNUNET_CRYPTO_hash (&withdraw_purpose, - ntohl (withdraw_purpose.purpose.size), + signatures, and compare the hashes to find + duplicates. */ + GNUNET_CRYPTO_hash (&sig, + sizeof (sig), &uuid[uuid_off]); for (unsigned int i = 0; iblinded_planchet, + &pd->denom_pub_hash, + &bch)) { - struct TALER_WithdrawRequestPS req = { - .purpose.size = htonl (sizeof (req)), - .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW), - .reserve_pub = wh->reserve_pub, - .h_denomination_pub = pd->denom_pub_hash - }; - - TALER_amount_hton (&req.amount_with_fee, - &wh->requested_amount); - if (GNUNET_OK != - TALER_coin_ev_hash (&pd->blinded_planchet, - &pd->denom_pub_hash, - &req.h_coin_envelope)) - { - GNUNET_break (0); - GNUNET_free (wh); - return NULL; - } - GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv, - &req, - &reserve_sig.eddsa_signature); + GNUNET_break (0); + GNUNET_free (wh); + return NULL; } + TALER_wallet_withdraw_sign (&pd->denom_pub_hash, + &wh->requested_amount, + &bch, + reserve_priv, + &reserve_sig); { json_t *withdraw_obj = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("denom_pub_hash", diff --git a/src/util/crypto.c b/src/util/crypto.c index 1b486d404..13b9188c5 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -246,90 +246,6 @@ TALER_cs_refresh_nonce_derive ( } -void -TALER_planchet_blinding_secret_create ( - const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values, - union TALER_DenominationBlindingKeyP *bks) -{ - switch (alg_values->cipher) - { - case TALER_DENOMINATION_INVALID: - GNUNET_break (0); - return; - case TALER_DENOMINATION_RSA: - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (&bks->rsa_bks, - sizeof (bks->rsa_bks), - "bks", - strlen ("bks"), - ps, - sizeof(*ps), - NULL, - 0)); - return; - case TALER_DENOMINATION_CS: - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (&bks->nonce, - sizeof (bks->nonce), - "bseed", - strlen ("bseed"), - ps, - sizeof(*ps), - &alg_values->details.cs_values, - sizeof(alg_values->details.cs_values), - NULL, - 0)); - return; - default: - GNUNET_break (0); - } -} - - -// FIXME: move to denom.c? -void -TALER_planchet_setup_coin_priv ( - const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values, - struct TALER_CoinSpendPrivateKeyP *coin_priv) -{ - switch (alg_values->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (coin_priv, - sizeof (*coin_priv), - "coin", - strlen ("coin"), - ps, - sizeof(*ps), - NULL, - 0)); - break; - case TALER_DENOMINATION_CS: - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (coin_priv, - sizeof (*coin_priv), - "coin", - strlen ("coin"), - ps, - sizeof(*ps), - &alg_values->details.cs_values, - sizeof(alg_values->details.cs_values), - NULL, - 0)); - break; - default: - GNUNET_break (0); - return; - } - coin_priv->eddsa_priv.d[0] &= 248; - coin_priv->eddsa_priv.d[31] &= 127; - coin_priv->eddsa_priv.d[31] |= 64; -} - - enum GNUNET_GenericReturnValue TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, const struct TALER_ExchangeWithdrawValues *alg_values, @@ -369,26 +285,6 @@ TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd) } -void -TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet) -{ - switch (blinded_planchet->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg); - break; - case TALER_DENOMINATION_CS: - memset (blinded_planchet, - 0, - sizeof (*blinded_planchet)); - /* nothing to do for CS */ - break; - default: - GNUNET_break (0); - } -} - - enum GNUNET_GenericReturnValue TALER_planchet_to_coin ( const struct TALER_DenominationPublicKey *dk, @@ -498,44 +394,6 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, } -enum GNUNET_GenericReturnValue -TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet, - const struct TALER_DenominationHash *denom_hash, - struct TALER_BlindedCoinHash *bch) -{ - struct GNUNET_HashContext *hash_context; - - hash_context = GNUNET_CRYPTO_hash_context_start (); - GNUNET_CRYPTO_hash_context_read (hash_context, - denom_hash, - sizeof(*denom_hash)); - switch (blinded_planchet->cipher) - { - case TALER_DENOMINATION_RSA: - GNUNET_CRYPTO_hash_context_read ( - hash_context, - blinded_planchet->details.rsa_blinded_planchet.blinded_msg, - blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size); - break; - case TALER_DENOMINATION_CS: - // FIXME: simplifies once 'nonce' is removed - // from TALER_BlindedCsPlanchet! - GNUNET_CRYPTO_hash_context_read ( - hash_context, - &blinded_planchet->details.cs_blinded_planchet.c[0], - sizeof (struct GNUNET_CRYPTO_CsC) * 2); - break; - default: - GNUNET_break (0); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return GNUNET_SYSERR; - } - GNUNET_CRYPTO_hash_context_finish (hash_context, - &bch->hash); - return GNUNET_OK; -} - - void TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_AgeHash *age_commitment_hash, diff --git a/src/util/denom.c b/src/util/denom.c index 68ad04f39..ee488192b 100644 --- a/src/util/denom.c +++ b/src/util/denom.c @@ -82,28 +82,6 @@ TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv, } -enum GNUNET_GenericReturnValue -TALER_denom_cs_derive_r_public (const struct TALER_CsNonce *nonce, - const struct - TALER_DenominationPrivateKey *denom_priv, - struct TALER_DenominationCSPublicRPairP *r_pub) -{ - if (denom_priv->cipher != TALER_DENOMINATION_CS) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - struct GNUNET_CRYPTO_CsRSecret r[2]; - GNUNET_CRYPTO_cs_r_derive (&nonce->nonce, - &denom_priv->details.cs_private_key, - r); - GNUNET_CRYPTO_cs_r_get_public (&r[0], &r_pub->r_pub[0]); - GNUNET_CRYPTO_cs_r_get_public (&r[1], &r_pub->r_pub[1]); - return GNUNET_OK; -} - - enum GNUNET_GenericReturnValue TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, const struct TALER_DenominationPrivateKey *denom_priv, @@ -112,13 +90,11 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, memset (denom_sig, 0, sizeof (*denom_sig)); - if (blinded_planchet->cipher != denom_priv->cipher) { GNUNET_break (0); return GNUNET_SYSERR; } - switch (denom_priv->cipher) { case TALER_DENOMINATION_INVALID: @@ -140,11 +116,11 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, case TALER_DENOMINATION_CS: { struct GNUNET_CRYPTO_CsRSecret r[2]; + GNUNET_CRYPTO_cs_r_derive ( &blinded_planchet->details.cs_blinded_planchet.nonce.nonce, &denom_priv->details.cs_private_key, r); - denom_sig->details.blinded_cs_answer.b = GNUNET_CRYPTO_cs_sign_derive (&denom_priv->details.cs_private_key, r, @@ -154,7 +130,6 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, cs_blinded_planchet.nonce.nonce, &denom_sig->details.blinded_cs_answer. s_scalar); - denom_sig->cipher = TALER_DENOMINATION_CS; } return GNUNET_OK; @@ -268,8 +243,8 @@ TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, htonl (denom_pub->age_mask.mask), htonl ((uint32_t) denom_pub->cipher) }; - struct GNUNET_HashContext *hc; + hc = GNUNET_CRYPTO_hash_context_start (); GNUNET_CRYPTO_hash_context_read (hc, opt, @@ -444,7 +419,6 @@ TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub) denom_pub->cipher = TALER_DENOMINATION_INVALID; return; case TALER_DENOMINATION_CS: - // ATM nothing needs to be freed, but check again after implementation. return; default: GNUNET_assert (0); @@ -468,7 +442,6 @@ TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv) denom_priv->cipher = TALER_DENOMINATION_INVALID; return; case TALER_DENOMINATION_CS: - // ATM nothing needs to be freed, but check again after implementation. return; default: GNUNET_assert (0); @@ -492,7 +465,6 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig) denom_sig->cipher = TALER_DENOMINATION_INVALID; return; case TALER_DENOMINATION_CS: - // ATM nothing needs to be freed, but check again after implementation. return; default: GNUNET_assert (0); @@ -518,7 +490,6 @@ TALER_blinded_denom_sig_free ( denom_sig->cipher = TALER_DENOMINATION_INVALID; return; case TALER_DENOMINATION_CS: - // ATM nothing needs to be freed, but check again after implementation. return; default: GNUNET_assert (0); @@ -546,7 +517,6 @@ TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst, denom_src->details.rsa_public_key); return; case TALER_DENOMINATION_CS: - // In Case of CS, the above is already a deep copy *denom_dst = *denom_src; return; default: GNUNET_assert (0); @@ -569,7 +539,6 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst, denom_src->details.rsa_signature); return; case TALER_DENOMINATION_CS: - // In Case of CS, the above is already a deep copy *denom_dst = *denom_src; return; default: GNUNET_assert (0); @@ -593,7 +562,6 @@ TALER_blinded_denom_sig_deep_copy ( denom_src->details.blinded_rsa_signature); return; case TALER_DENOMINATION_CS: - // In Case of CS, the above is already a deep copy *denom_dst = *denom_src; return; default: GNUNET_assert (0); @@ -734,4 +702,143 @@ TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp, } +void +TALER_planchet_blinding_secret_create ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + union TALER_DenominationBlindingKeyP *bks) +{ + switch (alg_values->cipher) + { + case TALER_DENOMINATION_INVALID: + GNUNET_break (0); + return; + case TALER_DENOMINATION_RSA: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&bks->rsa_bks, + sizeof (bks->rsa_bks), + "bks", + strlen ("bks"), + ps, + sizeof(*ps), + NULL, + 0)); + return; + case TALER_DENOMINATION_CS: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&bks->nonce, + sizeof (bks->nonce), + "bseed", + strlen ("bseed"), + ps, + sizeof(*ps), + &alg_values->details.cs_values, + sizeof(alg_values->details.cs_values), + NULL, + 0)); + return; + default: + GNUNET_break (0); + } +} + + +void +TALER_planchet_setup_coin_priv ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_CoinSpendPrivateKeyP *coin_priv) +{ + switch (alg_values->cipher) + { + case TALER_DENOMINATION_RSA: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (coin_priv, + sizeof (*coin_priv), + "coin", + strlen ("coin"), + ps, + sizeof(*ps), + NULL, + 0)); + break; + case TALER_DENOMINATION_CS: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (coin_priv, + sizeof (*coin_priv), + "coin", + strlen ("coin"), + ps, + sizeof(*ps), + &alg_values->details.cs_values, + sizeof(alg_values->details.cs_values), + NULL, + 0)); + break; + default: + GNUNET_break (0); + return; + } + coin_priv->eddsa_priv.d[0] &= 248; + coin_priv->eddsa_priv.d[31] &= 127; + coin_priv->eddsa_priv.d[31] |= 64; +} + + +void +TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet) +{ + switch (blinded_planchet->cipher) + { + case TALER_DENOMINATION_RSA: + GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg); + break; + case TALER_DENOMINATION_CS: + memset (blinded_planchet, + 0, + sizeof (*blinded_planchet)); + /* nothing to do for CS */ + break; + default: + GNUNET_break (0); + } +} + + +enum GNUNET_GenericReturnValue +TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet, + const struct TALER_DenominationHash *denom_hash, + struct TALER_BlindedCoinHash *bch) +{ + struct GNUNET_HashContext *hash_context; + + hash_context = GNUNET_CRYPTO_hash_context_start (); + GNUNET_CRYPTO_hash_context_read (hash_context, + denom_hash, + sizeof(*denom_hash)); + switch (blinded_planchet->cipher) + { + case TALER_DENOMINATION_RSA: + GNUNET_CRYPTO_hash_context_read ( + hash_context, + blinded_planchet->details.rsa_blinded_planchet.blinded_msg, + blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size); + break; + case TALER_DENOMINATION_CS: + GNUNET_CRYPTO_hash_context_read ( + hash_context, + &blinded_planchet->details.cs_blinded_planchet.c[0], + sizeof (struct GNUNET_CRYPTO_CsC) * 2); + break; + default: + GNUNET_break (0); + GNUNET_CRYPTO_hash_context_abort (hash_context); + return GNUNET_SYSERR; + } + GNUNET_CRYPTO_hash_context_finish (hash_context, + &bch->hash); + return GNUNET_OK; +} + + /* end of denom.c */ diff --git a/src/util/taler-exchange-secmod-cs.c b/src/util/taler-exchange-secmod-cs.c index 17fb23b3d..ab3a86fa8 100644 --- a/src/util/taler-exchange-secmod-cs.c +++ b/src/util/taler-exchange-secmod-cs.c @@ -281,7 +281,6 @@ handle_sign_request (struct TES_Client *client, { struct DenominationKey *dk; struct GNUNET_CRYPTO_CsRSecret r[2]; - struct TALER_BlindedDenominationCsSignAnswer cs_answer; struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); @@ -326,8 +325,9 @@ handle_sign_request (struct TES_Client *client, GNUNET_assert (dk->rc < UINT_MAX); dk->rc++; GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); - - GNUNET_CRYPTO_cs_r_derive (&sr->planchet.nonce.nonce, &dk->denom_priv, r); + GNUNET_CRYPTO_cs_r_derive (&sr->planchet.nonce.nonce, + &dk->denom_priv, + r); cs_answer.b = GNUNET_CRYPTO_cs_sign_derive (&dk->denom_priv, r, sr->planchet.c, diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c index 94d3167e3..fbf30e3a4 100644 --- a/src/util/test_crypto.c +++ b/src/util/test_crypto.c @@ -175,6 +175,38 @@ test_planchets_rsa (void) } +/** + * @brief Function for CS signatures to derive public R_0 and R_1 + * + * @param nonce withdraw nonce from a client + * @param denom_priv denomination privkey as long-term secret + * @param r_pub the resulting R_0 and R_1 + * @return enum GNUNET_GenericReturnValue + */ +static enum GNUNET_GenericReturnValue +derive_r_public ( + const struct TALER_CsNonce *nonce, + const struct TALER_DenominationPrivateKey *denom_priv, + struct TALER_DenominationCSPublicRPairP *r_pub) +{ + struct GNUNET_CRYPTO_CsRSecret r[2]; + + if (denom_priv->cipher != TALER_DENOMINATION_CS) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + GNUNET_CRYPTO_cs_r_derive (&nonce->nonce, + &denom_priv->details.cs_private_key, + r); + GNUNET_CRYPTO_cs_r_get_public (&r[0], + &r_pub->r_pub[0]); + GNUNET_CRYPTO_cs_r_get_public (&r[1], + &r_pub->r_pub[1]); + return GNUNET_OK; +} + + /** * Test the basic planchet functionality of creating a fresh planchet with CS denomination * and extracting the respective signature. @@ -207,7 +239,7 @@ test_planchets_cs (void) &ps, &pd.blinded_planchet.details.cs_blinded_planchet.nonce); GNUNET_assert (GNUNET_OK == - TALER_denom_cs_derive_r_public ( + derive_r_public ( &pd.blinded_planchet.details.cs_blinded_planchet.nonce, &dk_priv, &alg_values.details.cs_values)); diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c index 669ea6dd5..1dd2302b4 100644 --- a/src/util/wallet_signatures.c +++ b/src/util/wallet_signatures.c @@ -285,4 +285,52 @@ TALER_wallet_melt_verify ( } +void +TALER_wallet_withdraw_sign ( + const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHash *bch, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_WithdrawRequestPS req = { + .purpose.size = htonl (sizeof (req)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW), + .h_denomination_pub = *h_denom_pub, + .h_coin_envelope = *bch + }; + + TALER_amount_hton (&req.amount_with_fee, + amount_with_fee); + GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv, + &req, + &reserve_sig->eddsa_signature); +} + + +enum GNUNET_GenericReturnValue +TALER_wallet_withdraw_verify ( + const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHash *bch, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_WithdrawRequestPS wsrd = { + .purpose.size = htonl (sizeof (wsrd)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW), + .h_denomination_pub = *h_denom_pub, + .h_coin_envelope = *bch + }; + + TALER_amount_hton (&wsrd.amount_with_fee, + amount_with_fee); + return GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, + &wsrd, + &reserve_sig->eddsa_signature, + &reserve_pub->eddsa_pub); +} + + /* end of wallet_signatures.c */ -- cgit v1.2.3