-address misc. fixmes

This commit is contained in:
Christian Grothoff 2022-02-12 00:52:19 +01:00
parent 3b1e742dde
commit 94a5359494
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
12 changed files with 341 additions and 309 deletions

View File

@ -508,12 +508,7 @@ handle_reserve_out (void *cls,
struct GNUNET_TIME_Timestamp valid_start; struct GNUNET_TIME_Timestamp valid_start;
struct GNUNET_TIME_Timestamp expire_withdraw; struct GNUNET_TIME_Timestamp expire_withdraw;
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
struct TALER_WithdrawRequestPS wsrd = { struct TALER_DenominationHash h_denom_pub;
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
.purpose.size = htonl (sizeof (wsrd)),
.reserve_pub = *reserve_pub,
.h_coin_envelope = *h_blind_ev
};
/* should be monotonically increasing */ /* should be monotonically increasing */
GNUNET_assert (rowid >= ppr.last_reserve_out_serial_id); GNUNET_assert (rowid >= ppr.last_reserve_out_serial_id);
@ -523,7 +518,7 @@ handle_reserve_out (void *cls,
initializes wsrd.h_denomination_pub! */ initializes wsrd.h_denomination_pub! */
qs = TALER_ARL_get_denomination_info (denom_pub, qs = TALER_ARL_get_denomination_info (denom_pub,
&issue, &issue,
&wsrd.h_denomination_pub); &h_denom_pub);
if (0 > qs) if (0 > qs)
{ {
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == 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", GNUNET_JSON_pack_data_auto ("reserve_pub",
reserve_pub), reserve_pub),
GNUNET_JSON_pack_data_auto ("denompub_h", GNUNET_JSON_pack_data_auto ("denompub_h",
&wsrd.h_denomination_pub))); &h_denom_pub)));
} }
/* check reserve_sig (first: setup remaining members of wsrd) */ /* check reserve_sig (first: setup remaining members of wsrd) */
TALER_amount_hton (&wsrd.amount_with_fee,
amount_with_fee);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, TALER_wallet_withdraw_verify (&h_denom_pub,
&wsrd, amount_with_fee,
&reserve_sig->eddsa_signature, h_blind_ev,
&reserve_pub->eddsa_pub)) reserve_pub,
reserve_sig))
{ {
TALER_ARL_report (report_bad_sig_losses, TALER_ARL_report (report_bad_sig_losses,
GNUNET_JSON_PACK ( GNUNET_JSON_PACK (

View File

@ -90,10 +90,21 @@ reply_withdraw_insufficient_funds (
*/ */
struct WithdrawContext 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. * Blinded planchet.
@ -143,8 +154,6 @@ withdraw_transaction (void *cls,
uint64_t ruuid; uint64_t ruuid;
now = GNUNET_TIME_timestamp_get (); 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, qs = TEH_plugin->do_withdraw (TEH_plugin->cls,
&wc->collectable, &wc->collectable,
now, now,
@ -173,7 +182,6 @@ withdraw_transaction (void *cls,
{ {
struct TALER_EXCHANGEDB_ReserveHistory *rh; struct TALER_EXCHANGEDB_ReserveHistory *rh;
struct TALER_Amount balance; struct TALER_Amount balance;
struct TALER_Amount requested_amount;
TEH_plugin->rollback (TEH_plugin->cls); TEH_plugin->rollback (TEH_plugin->cls);
// FIXME: maybe start read-committed here? // FIXME: maybe start read-committed here?
@ -192,7 +200,7 @@ withdraw_transaction (void *cls,
/* The reserve does not have the required amount (actual /* The reserve does not have the required amount (actual
* amount + withdraw fee) */ * amount + withdraw fee) */
qs = TEH_plugin->get_reserve_history (TEH_plugin->cls, qs = TEH_plugin->get_reserve_history (TEH_plugin->cls,
&wc->wsrd.reserve_pub, &wc->collectable.reserve_pub,
&balance, &balance,
&rh); &rh);
if (NULL == rh) if (NULL == rh)
@ -204,12 +212,11 @@ withdraw_transaction (void *cls,
"reserve history"); "reserve history");
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
TALER_amount_ntoh (&requested_amount, *mhd_ret = reply_withdraw_insufficient_funds (
&wc->wsrd.amount_with_fee); connection,
*mhd_ret = reply_withdraw_insufficient_funds (connection, &balance,
&balance, &wc->collectable.amount_with_fee,
&requested_amount, rh);
rh);
TEH_plugin->free_reserve_history (TEH_plugin->cls, TEH_plugin->free_reserve_history (TEH_plugin->cls,
rh); rh);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
@ -287,7 +294,7 @@ check_request_idempotent (struct TEH_RequestContext *rc,
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls, qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
&wc->wsrd.h_coin_envelope, &wc->collectable.h_coin_envelope,
&wc->collectable); &wc->collectable);
if (0 > qs) if (0 > qs)
{ {
@ -336,8 +343,8 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0], GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]), strlen (args[0]),
&wc.wsrd.reserve_pub, &wc.collectable.reserve_pub,
sizeof (wc.wsrd.reserve_pub))) sizeof (wc.collectable.reserve_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection, 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, TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
NULL); 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 != if (GNUNET_OK !=
TALER_coin_ev_hash (&wc.blinded_planchet, TALER_coin_ev_hash (&wc.blinded_planchet,
&wc.collectable.denom_pub_hash, &wc.collectable.denom_pub_hash,
&wc.wsrd.h_coin_envelope)) &wc.collectable.h_coin_envelope))
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -483,15 +480,15 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
NULL); NULL);
} }
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify ( TALER_wallet_withdraw_verify (&wc.collectable.denom_pub_hash,
TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, &wc.collectable.amount_with_fee,
&wc.wsrd, &wc.collectable.h_coin_envelope,
&wc.collectable.reserve_sig.eddsa_signature, &wc.collectable.reserve_pub,
&wc.wsrd.reserve_pub.eddsa_pub)) &wc.collectable.reserve_sig))
{ {
TALER_LOG_WARNING ( GNUNET_break_op (0);
"Client supplied invalid signature for withdraw request\n");
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (rc->connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_FORBIDDEN, MHD_HTTP_FORBIDDEN,

View File

@ -857,9 +857,6 @@ struct TALER_BlindedCsPlanchet
/** /**
* Public nonce. * 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; struct TALER_CsNonce nonce;
}; };
@ -1085,31 +1082,12 @@ void
TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); 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. * Blind coin for blind signing with @a dk using blinding secret @a coin_bks.
* *
* NOTE/FIXME: As a particular oddity, the @a blinded_planchet * NOTE: As a particular oddity, the @a blinded_planchet is only partially
* is only partially initialized by this function in the * initialized by this function in the case of CS-denominations. Here, the
* case of CS-denominations. Here, the 'nonce' must * 'nonce' must be initialized separately!
* 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!
* *
* @param dk denomination public key to blind for * @param dk denomination public key to blind for
* @param coin_bks blinding secret to use * @param coin_bks blinding secret to use
@ -1564,8 +1542,8 @@ TALER_planchet_blinding_secret_create (
* @param coin_priv coin private key * @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] 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 * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and
* other withdraw operations, pd->blinded_planchet.cipher will be set * other withdraw operations, `pd->blinded_planchet.cipher` will be set
* to cipher from dk * to cipher from @a dk
* @return #GNUNET_OK on success * @return #GNUNET_OK on success
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
@ -1574,8 +1552,7 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
const union TALER_DenominationBlindingKeyP *bks, const union TALER_DenominationBlindingKeyP *bks,
const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_CoinSpendPrivateKeyP *coin_priv,
struct TALER_CoinPubHash *c_hash, 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); 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. * Verify recoup signature.
* *

View File

@ -440,13 +440,7 @@ struct TALER_WithdrawRequestPS
struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/** /**
* Reserve public key (which reserve to withdraw from). This is * Value of the coin being exchanged (matching the denomination key)
* the public key which must match the signature.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* Value of the coin being exchangeed (matching the denomination key)
* plus the transaction fee. We include this in what is being * plus the transaction fee. We include this in what is being
* signed so that we can verify a reserve's remaining total balance * signed so that we can verify a reserve's remaining total balance
* without needing to access the respective denomination key * without needing to access the respective denomination key

View File

@ -124,7 +124,8 @@ TALER_EXCHANGE_parse_reserve_history (
"WITHDRAW")) "WITHDRAW"))
{ {
struct TALER_ReserveSignatureP sig; 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 TALER_Amount withdraw_fee;
struct GNUNET_JSON_Specification withdraw_spec[] = { struct GNUNET_JSON_Specification withdraw_spec[] = {
GNUNET_JSON_spec_fixed_auto ("reserve_sig", GNUNET_JSON_spec_fixed_auto ("reserve_sig",
@ -132,9 +133,9 @@ TALER_EXCHANGE_parse_reserve_history (
TALER_JSON_spec_amount_any ("withdraw_fee", TALER_JSON_spec_amount_any ("withdraw_fee",
&withdraw_fee), &withdraw_fee),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub", GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
&withdraw_purpose.h_denomination_pub), &h_denom_pub),
GNUNET_JSON_spec_fixed_auto ("h_coin_envelope", GNUNET_JSON_spec_fixed_auto ("h_coin_envelope",
&withdraw_purpose.h_coin_envelope), &bch),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
@ -147,19 +148,14 @@ TALER_EXCHANGE_parse_reserve_history (
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; 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 */ /* Check that the signature is a valid withdraw request */
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, TALER_wallet_withdraw_verify (&h_denom_pub,
&withdraw_purpose, &amount,
&sig.eddsa_signature, &bch,
&reserve_pub->eddsa_pub)) reserve_pub,
&sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (withdraw_spec); GNUNET_JSON_parse_free (withdraw_spec);
@ -172,8 +168,7 @@ TALER_EXCHANGE_parse_reserve_history (
key_state = TALER_EXCHANGE_get_keys (exchange); key_state = TALER_EXCHANGE_get_keys (exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
&withdraw_purpose. &h_denom_pub);
h_denomination_pub);
if ( (GNUNET_YES != if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&withdraw_fee, TALER_amount_cmp_currency (&withdraw_fee,
&dki->fee_withdraw)) || &dki->fee_withdraw)) ||
@ -193,10 +188,10 @@ TALER_EXCHANGE_parse_reserve_history (
/* Check check that the same withdraw transaction /* Check check that the same withdraw transaction
isn't listed twice by the exchange. We use the isn't listed twice by the exchange. We use the
"uuid" array to remember the hashes of all "uuid" array to remember the hashes of all
purposes, and compare the hashes to find signatures, and compare the hashes to find
duplicates. */// duplicates. */
GNUNET_CRYPTO_hash (&withdraw_purpose, GNUNET_CRYPTO_hash (&sig,
ntohl (withdraw_purpose.purpose.size), sizeof (sig),
&uuid[uuid_off]); &uuid[uuid_off]);
for (unsigned int i = 0; i<uuid_off; i++) for (unsigned int i = 0; i<uuid_off; i++)
{ {

View File

@ -399,10 +399,11 @@ TALER_EXCHANGE_refreshes_reveal (
TALER_planchet_blinding_secret_create (&coin_ps, TALER_planchet_blinding_secret_create (&coin_ps,
&alg_values[i], &alg_values[i],
&bks); &bks);
TALER_cs_refresh_nonce_derive ( if (TALER_DENOMINATION_CS == alg_values[i].cipher)
rms, TALER_cs_refresh_nonce_derive (
i, rms,
&pd.blinded_planchet.details.cs_blinded_planchet.nonce); i,
&pd.blinded_planchet.details.cs_blinded_planchet.nonce);
if (GNUNET_OK != if (GNUNET_OK !=
TALER_planchet_prepare (&md.fresh_pks[i], TALER_planchet_prepare (&md.fresh_pks[i],
&alg_values[i], &alg_values[i],

View File

@ -380,6 +380,7 @@ TALER_EXCHANGE_withdraw2 (
const struct TALER_EXCHANGE_DenomPublicKey *dk; const struct TALER_EXCHANGE_DenomPublicKey *dk;
struct TALER_ReserveSignatureP reserve_sig; struct TALER_ReserveSignatureP reserve_sig;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
struct TALER_BlindedCoinHash bch;
keys = TALER_EXCHANGE_get_keys (exchange); keys = TALER_EXCHANGE_get_keys (exchange);
if (NULL == keys) if (NULL == keys)
@ -428,31 +429,22 @@ TALER_EXCHANGE_withdraw2 (
"/reserves/%s/withdraw", "/reserves/%s/withdraw",
pub_str); pub_str);
} }
// FIXME: move this to libtalerutil!
{
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, if (GNUNET_OK !=
&wh->requested_amount); TALER_coin_ev_hash (&pd->blinded_planchet,
if (GNUNET_OK != &pd->denom_pub_hash,
TALER_coin_ev_hash (&pd->blinded_planchet, &bch))
&pd->denom_pub_hash, {
&req.h_coin_envelope)) GNUNET_break (0);
{ GNUNET_free (wh);
GNUNET_break (0); return NULL;
GNUNET_free (wh);
return NULL;
}
GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
&req,
&reserve_sig.eddsa_signature);
} }
TALER_wallet_withdraw_sign (&pd->denom_pub_hash,
&wh->requested_amount,
&bch,
reserve_priv,
&reserve_sig);
{ {
json_t *withdraw_obj = GNUNET_JSON_PACK ( json_t *withdraw_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("denom_pub_hash", GNUNET_JSON_pack_data_auto ("denom_pub_hash",

View File

@ -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 enum GNUNET_GenericReturnValue
TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
const struct TALER_ExchangeWithdrawValues *alg_values, 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 enum GNUNET_GenericReturnValue
TALER_planchet_to_coin ( TALER_planchet_to_coin (
const struct TALER_DenominationPublicKey *dk, 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 void
TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_AgeHash *age_commitment_hash, const struct TALER_AgeHash *age_commitment_hash,

View File

@ -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 enum GNUNET_GenericReturnValue
TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
const struct TALER_DenominationPrivateKey *denom_priv, const struct TALER_DenominationPrivateKey *denom_priv,
@ -112,13 +90,11 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
memset (denom_sig, memset (denom_sig,
0, 0,
sizeof (*denom_sig)); sizeof (*denom_sig));
if (blinded_planchet->cipher != denom_priv->cipher) if (blinded_planchet->cipher != denom_priv->cipher)
{ {
GNUNET_break (0); GNUNET_break (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
switch (denom_priv->cipher) switch (denom_priv->cipher)
{ {
case TALER_DENOMINATION_INVALID: case TALER_DENOMINATION_INVALID:
@ -140,11 +116,11 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
{ {
struct GNUNET_CRYPTO_CsRSecret r[2]; struct GNUNET_CRYPTO_CsRSecret r[2];
GNUNET_CRYPTO_cs_r_derive ( GNUNET_CRYPTO_cs_r_derive (
&blinded_planchet->details.cs_blinded_planchet.nonce.nonce, &blinded_planchet->details.cs_blinded_planchet.nonce.nonce,
&denom_priv->details.cs_private_key, &denom_priv->details.cs_private_key,
r); r);
denom_sig->details.blinded_cs_answer.b = denom_sig->details.blinded_cs_answer.b =
GNUNET_CRYPTO_cs_sign_derive (&denom_priv->details.cs_private_key, GNUNET_CRYPTO_cs_sign_derive (&denom_priv->details.cs_private_key,
r, r,
@ -154,7 +130,6 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
cs_blinded_planchet.nonce.nonce, cs_blinded_planchet.nonce.nonce,
&denom_sig->details.blinded_cs_answer. &denom_sig->details.blinded_cs_answer.
s_scalar); s_scalar);
denom_sig->cipher = TALER_DENOMINATION_CS; denom_sig->cipher = TALER_DENOMINATION_CS;
} }
return GNUNET_OK; return GNUNET_OK;
@ -268,8 +243,8 @@ TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub,
htonl (denom_pub->age_mask.mask), htonl (denom_pub->age_mask.mask),
htonl ((uint32_t) denom_pub->cipher) htonl ((uint32_t) denom_pub->cipher)
}; };
struct GNUNET_HashContext *hc; struct GNUNET_HashContext *hc;
hc = GNUNET_CRYPTO_hash_context_start (); hc = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hc, GNUNET_CRYPTO_hash_context_read (hc,
opt, opt,
@ -444,7 +419,6 @@ TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub)
denom_pub->cipher = TALER_DENOMINATION_INVALID; denom_pub->cipher = TALER_DENOMINATION_INVALID;
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// ATM nothing needs to be freed, but check again after implementation.
return; return;
default: default:
GNUNET_assert (0); GNUNET_assert (0);
@ -468,7 +442,6 @@ TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv)
denom_priv->cipher = TALER_DENOMINATION_INVALID; denom_priv->cipher = TALER_DENOMINATION_INVALID;
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// ATM nothing needs to be freed, but check again after implementation.
return; return;
default: default:
GNUNET_assert (0); GNUNET_assert (0);
@ -492,7 +465,6 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig)
denom_sig->cipher = TALER_DENOMINATION_INVALID; denom_sig->cipher = TALER_DENOMINATION_INVALID;
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// ATM nothing needs to be freed, but check again after implementation.
return; return;
default: default:
GNUNET_assert (0); GNUNET_assert (0);
@ -518,7 +490,6 @@ TALER_blinded_denom_sig_free (
denom_sig->cipher = TALER_DENOMINATION_INVALID; denom_sig->cipher = TALER_DENOMINATION_INVALID;
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// ATM nothing needs to be freed, but check again after implementation.
return; return;
default: default:
GNUNET_assert (0); GNUNET_assert (0);
@ -546,7 +517,6 @@ TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst,
denom_src->details.rsa_public_key); denom_src->details.rsa_public_key);
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// In Case of CS, the above is already a deep copy *denom_dst = *denom_src;
return; return;
default: default:
GNUNET_assert (0); GNUNET_assert (0);
@ -569,7 +539,6 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst,
denom_src->details.rsa_signature); denom_src->details.rsa_signature);
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// In Case of CS, the above is already a deep copy *denom_dst = *denom_src;
return; return;
default: default:
GNUNET_assert (0); GNUNET_assert (0);
@ -593,7 +562,6 @@ TALER_blinded_denom_sig_deep_copy (
denom_src->details.blinded_rsa_signature); denom_src->details.blinded_rsa_signature);
return; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
// In Case of CS, the above is already a deep copy *denom_dst = *denom_src;
return; return;
default: default:
GNUNET_assert (0); 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 */ /* end of denom.c */

View File

@ -281,7 +281,6 @@ handle_sign_request (struct TES_Client *client,
{ {
struct DenominationKey *dk; struct DenominationKey *dk;
struct GNUNET_CRYPTO_CsRSecret r[2]; struct GNUNET_CRYPTO_CsRSecret r[2];
struct TALER_BlindedDenominationCsSignAnswer cs_answer; struct TALER_BlindedDenominationCsSignAnswer cs_answer;
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 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); GNUNET_assert (dk->rc < UINT_MAX);
dk->rc++; dk->rc++;
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_CRYPTO_cs_r_derive (&sr->planchet.nonce.nonce,
GNUNET_CRYPTO_cs_r_derive (&sr->planchet.nonce.nonce, &dk->denom_priv, r); &dk->denom_priv,
r);
cs_answer.b = GNUNET_CRYPTO_cs_sign_derive (&dk->denom_priv, cs_answer.b = GNUNET_CRYPTO_cs_sign_derive (&dk->denom_priv,
r, r,
sr->planchet.c, sr->planchet.c,

View File

@ -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 * Test the basic planchet functionality of creating a fresh planchet with CS denomination
* and extracting the respective signature. * and extracting the respective signature.
@ -207,7 +239,7 @@ test_planchets_cs (void)
&ps, &ps,
&pd.blinded_planchet.details.cs_blinded_planchet.nonce); &pd.blinded_planchet.details.cs_blinded_planchet.nonce);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_denom_cs_derive_r_public ( derive_r_public (
&pd.blinded_planchet.details.cs_blinded_planchet.nonce, &pd.blinded_planchet.details.cs_blinded_planchet.nonce,
&dk_priv, &dk_priv,
&alg_values.details.cs_values)); &alg_values.details.cs_values));

View File

@ -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 */ /* end of wallet_signatures.c */