implement withdraw (nonce reuse check missing)
This commit is contained in:
parent
4c7aa09784
commit
9074e66ebc
@ -37,10 +37,6 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[])
|
||||
{
|
||||
// TODO: should we have something similar to struct WithdrawContext?
|
||||
// as far as I can tell this isn't necessary because we don't have
|
||||
// other functions that the context should be passed to
|
||||
// struct CsRContext csrc;
|
||||
struct TALER_WithdrawNonce nonce;
|
||||
struct TALER_DenominationHash denom_pub_hash;
|
||||
struct TALER_DenominationCsPublicR r_pub;
|
||||
|
@ -2442,7 +2442,19 @@ TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
|
||||
msg,
|
||||
msg_size,
|
||||
ec);
|
||||
// TODO: case TALER_DENOMINATION_CS:
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (sizeof (struct TALER_BlindedCsPlanchet) != msg_size)
|
||||
{
|
||||
*ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||
return none;
|
||||
}
|
||||
struct TALER_BlindedCsPlanchet *blinded_cs_planchet = ((struct
|
||||
TALER_BlindedCsPlanchet
|
||||
*) msg);
|
||||
return TALER_CRYPTO_helper_cs_sign (ksh->helpers->csdh,
|
||||
&hd->h_details.h_cs,
|
||||
blinded_cs_planchet,
|
||||
ec);
|
||||
default:
|
||||
*ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||
return none;
|
||||
|
@ -98,15 +98,13 @@ struct WithdrawContext
|
||||
/**
|
||||
* Blinded planchet.
|
||||
*/
|
||||
void *blinded_msg;
|
||||
//FIXME:
|
||||
|
||||
/**
|
||||
* Number of bytes in @e blinded_msg.
|
||||
*/
|
||||
size_t blinded_msg_len;
|
||||
|
||||
/**
|
||||
* Set to the resulting signed coin data to be returned to the client.
|
||||
struct TALER_BlindedPlanchet blinded_planchet;
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_CollectableBlindcoin collectable;
|
||||
|
||||
@ -324,15 +322,48 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
{
|
||||
struct WithdrawContext wc;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
//FIXME:
|
||||
GNUNET_JSON_spec_varsize ("coin_ev",
|
||||
&wc.blinded_msg,
|
||||
&wc.blinded_msg_len),
|
||||
// field "coin_ev" will be parsed later due to different parsing depending
|
||||
// on denomination cipher, see coin_ev_..._spec
|
||||
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
|
||||
&wc.collectable.reserve_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
|
||||
&wc.collectable.denom_pub_hash),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
// holds pointer to coin_ev_rsa/cs_spec for freeing
|
||||
struct GNUNET_JSON_Specification *coin_ev_spec = NULL;
|
||||
struct GNUNET_JSON_Specification coin_ev_rsa_spec[] = {
|
||||
GNUNET_JSON_spec_varsize (
|
||||
"coin_ev",
|
||||
(void **) &wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
|
||||
&wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
json_t *coin_ev_cs_json;
|
||||
struct GNUNET_JSON_Specification coin_ev_cs_json_spec[] = {
|
||||
GNUNET_JSON_spec_json ("coin_ev",
|
||||
&coin_ev_cs_json),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct GNUNET_JSON_Specification coin_ev_cs_spec[] = {
|
||||
GNUNET_JSON_spec_fixed (
|
||||
"nonce",
|
||||
&wc.blinded_planchet.details.cs_blinded_planchet.nonce,
|
||||
sizeof (wc.blinded_planchet.details.cs_blinded_planchet.nonce)),
|
||||
GNUNET_JSON_spec_fixed (
|
||||
"c0",
|
||||
&wc.blinded_planchet.details.cs_blinded_planchet.c[0],
|
||||
sizeof (wc.blinded_planchet.details.cs_blinded_planchet.c[0])),
|
||||
GNUNET_JSON_spec_fixed (
|
||||
"c1",
|
||||
&wc.blinded_planchet.details.cs_blinded_planchet.c[1],
|
||||
sizeof (wc.blinded_planchet.details.cs_blinded_planchet.c[1])),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
enum TALER_ErrorCode ec;
|
||||
struct TEH_DenominationKey *dk;
|
||||
|
||||
@ -445,7 +476,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
return mret;
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME:
|
||||
if (0 >
|
||||
TALER_amount_add (&wc.collectable.amount_with_fee,
|
||||
&dk->meta.value,
|
||||
@ -456,6 +487,61 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
|
||||
NULL);
|
||||
// parse coin_ev field, must be done after dk lookup to know denom cipher
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
wc.blinded_planchet.cipher = dk->denom_pub.cipher;
|
||||
switch (wc.blinded_planchet.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
root,
|
||||
coin_ev_rsa_spec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
coin_ev_spec = coin_ev_rsa_spec;
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
// coin_ev for CS is nested
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
root,
|
||||
coin_ev_cs_json_spec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
coin_ev_cs_json,
|
||||
coin_ev_cs_spec);
|
||||
GNUNET_JSON_parse_free (coin_ev_cs_json_spec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
coin_ev_spec = coin_ev_cs_spec;
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (0 >
|
||||
TALER_amount_add (&wc.collectable.amount_with_fee,
|
||||
&dk->meta.value,
|
||||
&dk->meta.fee_withdraw))
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
|
||||
NULL);
|
||||
}
|
||||
TALER_amount_hton (&wc.wsrd.amount_with_fee,
|
||||
&wc.collectable.amount_with_fee);
|
||||
}
|
||||
TALER_amount_hton (&wc.wsrd.amount_with_fee,
|
||||
&wc.collectable.amount_with_fee);
|
||||
@ -468,9 +554,30 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
= htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
|
||||
wc.wsrd.h_denomination_pub
|
||||
= wc.collectable.denom_pub_hash;
|
||||
TALER_coin_ev_hash (wc.blinded_msg,
|
||||
wc.blinded_msg_len,
|
||||
&wc.wsrd.h_coin_envelope);
|
||||
switch (wc.blinded_planchet.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
TALER_coin_ev_hash (
|
||||
wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
|
||||
wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size,
|
||||
&wc.wsrd.h_coin_envelope);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
TALER_coin_ev_hash (
|
||||
&wc.blinded_planchet.details.cs_blinded_planchet,
|
||||
sizeof (wc.blinded_planchet.details.cs_blinded_planchet),
|
||||
&wc.wsrd.h_coin_envelope);
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (
|
||||
TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
|
||||
@ -481,23 +588,50 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
TALER_LOG_WARNING (
|
||||
"Client supplied invalid signature for withdraw request\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// TODO: if CS: check nonce for reuse
|
||||
|
||||
/* Sign before transaction! */
|
||||
ec = TALER_EC_NONE;
|
||||
wc.collectable.sig
|
||||
= TEH_keys_denomination_sign (&wc.collectable.denom_pub_hash,
|
||||
wc.blinded_msg,
|
||||
wc.blinded_msg_len,
|
||||
&ec);
|
||||
switch (wc.blinded_planchet.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
wc.collectable.sig = TEH_keys_denomination_sign (
|
||||
&wc.collectable.denom_pub_hash,
|
||||
wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
|
||||
wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size,
|
||||
&ec);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
wc.collectable.sig = TEH_keys_denomination_sign (
|
||||
&wc.collectable.denom_pub_hash,
|
||||
&wc.blinded_planchet.details.cs_blinded_planchet,
|
||||
sizeof (wc.blinded_planchet.details.cs_blinded_planchet),
|
||||
&ec);
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
return TALER_MHD_reply_with_ec (rc->connection,
|
||||
ec,
|
||||
NULL);
|
||||
@ -519,12 +653,16 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
(or we might have done it optimistically above). */
|
||||
TALER_blinded_denom_sig_free (&wc.collectable.sig);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
return mhd_ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up and send back final response */
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (NULL != coin_ev_spec)
|
||||
GNUNET_JSON_parse_free (coin_ev_spec);
|
||||
|
||||
{
|
||||
MHD_RESULT ret;
|
||||
|
@ -1332,6 +1332,30 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
|
||||
unsigned int expected_response_code);
|
||||
|
||||
|
||||
/**
|
||||
* Create a CS withdraw command, letting the caller specify
|
||||
* the desired amount as string and also re-using an existing
|
||||
* coin private key in the process (violating the specification,
|
||||
* which will result in an error when spending the coin!).
|
||||
*
|
||||
* @param label command label.
|
||||
* @param reserve_reference command providing us with a reserve to withdraw from
|
||||
* @param amount how much we withdraw.
|
||||
* @param coin_ref reference to (withdraw/reveal) command of a coin
|
||||
* from which we should re-use the private key
|
||||
* @param expected_response_code which HTTP response code
|
||||
* we expect from the exchange.
|
||||
* @return the withdraw command to be executed by the interpreter.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_withdraw_cs_amount_reuse_key (
|
||||
const char *label,
|
||||
const char *reserve_reference,
|
||||
const char *amount,
|
||||
const char *coin_ref,
|
||||
unsigned int expected_response_code);
|
||||
|
||||
|
||||
/**
|
||||
* Create withdraw command, letting the caller specify the
|
||||
* amount by a denomination key.
|
||||
|
@ -388,6 +388,7 @@ parse_denom_sig (void *cls,
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
// TODO: case TALER_DENOMINATION_CS:
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -483,6 +484,29 @@ parse_blinded_denom_sig (void *cls,
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_uint32 ("b",
|
||||
&denom_sig->details.blinded_cs_answer.b),
|
||||
GNUNET_JSON_spec_fixed_auto ("s",
|
||||
&denom_sig->details.blinded_cs_answer.
|
||||
s_scalar),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
|
@ -125,14 +125,21 @@ TALER_JSON_pack_blinded_denom_sig (
|
||||
switch (sig->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
ps.object
|
||||
= GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_RSA),
|
||||
GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
|
||||
sig->details.blinded_rsa_signature));
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_RSA),
|
||||
GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
|
||||
sig->details.blinded_rsa_signature));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_CS),
|
||||
GNUNET_JSON_pack_uint64 ("b",
|
||||
sig->details.blinded_cs_answer.b),
|
||||
GNUNET_JSON_pack_data_auto ("s",
|
||||
&sig->details.blinded_cs_answer.s_scalar));
|
||||
break;
|
||||
// TODO: case TALER_DENOMINATION_CS:
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
|
@ -58,11 +58,21 @@ struct TALER_EXCHANGE_WithdrawHandle
|
||||
*/
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* Reserve private key.
|
||||
*/
|
||||
const struct TALER_ReservePrivateKeyP *reserve_priv;
|
||||
|
||||
/**
|
||||
* Secrets of the planchet.
|
||||
*/
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
|
||||
/**
|
||||
* Details of the planchet.
|
||||
*/
|
||||
struct TALER_PlanchetDetail pd;
|
||||
|
||||
/**
|
||||
* Denomination key we are withdrawing.
|
||||
*/
|
||||
@ -162,24 +172,44 @@ withdraw_cs_stage_two_callback (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr)
|
||||
{
|
||||
struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
|
||||
// TODO: this should only be set for non-OK cases
|
||||
struct TALER_EXCHANGE_WithdrawResponse wr = {
|
||||
.hr = csrr->hr
|
||||
};
|
||||
|
||||
// switch (csrr->hr.http_status)
|
||||
// {
|
||||
// case MHD_HTTP_OK:
|
||||
// // TODO: implement rest of withdraw
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
wh->csrh = NULL;
|
||||
|
||||
// TODO: this should only be called for non-OK cases
|
||||
wh->cb (wh->cb_cls,
|
||||
&wr);
|
||||
TALER_EXCHANGE_withdraw_cancel (wh);
|
||||
GNUNET_assert (TALER_DENOMINATION_CS == wh->pk.key.cipher);
|
||||
|
||||
switch (csrr->hr.http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
wh->ps.cs_r_pub = csrr->details.success.r_pubs;
|
||||
TALER_blinding_secret_create (&wh->ps.blinding_key,
|
||||
wh->pk.key.cipher,
|
||||
&wh->ps.coin_priv,
|
||||
&wh->ps.cs_r_pub);
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&wh->pk.key,
|
||||
&wh->ps,
|
||||
&wh->c_hash,
|
||||
&wh->pd))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
}
|
||||
wh->wh2 = TALER_EXCHANGE_withdraw2 (wh->exchange,
|
||||
&wh->pd,
|
||||
wh->reserve_priv,
|
||||
&handle_reserve_withdraw_finished,
|
||||
wh);
|
||||
break;
|
||||
default:
|
||||
// the CSR request went wrong -> serve response to the callback
|
||||
struct TALER_EXCHANGE_WithdrawResponse wr = {
|
||||
.hr = csrr->hr
|
||||
};
|
||||
wh->cb (wh->cb_cls,
|
||||
&wr);
|
||||
TALER_EXCHANGE_withdraw_cancel (wh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -210,16 +240,19 @@ TALER_EXCHANGE_withdraw (
|
||||
TALER_EXCHANGE_WithdrawCallback res_cb,
|
||||
void *res_cb_cls)
|
||||
{
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_EXCHANGE_WithdrawHandle *wh;
|
||||
|
||||
wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
|
||||
wh->exchange = exchange;
|
||||
wh->cb = res_cb;
|
||||
wh->cb_cls = res_cb_cls;
|
||||
wh->pk = *pk;
|
||||
wh->reserve_priv = reserve_priv;
|
||||
wh->ps = *ps;
|
||||
wh->pk = *pk;
|
||||
wh->csrh = NULL;
|
||||
|
||||
TALER_denom_pub_deep_copy (&wh->pk.key,
|
||||
&pk->key);
|
||||
switch (pk->key.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
@ -227,27 +260,28 @@ TALER_EXCHANGE_withdraw (
|
||||
TALER_planchet_prepare (&pk->key,
|
||||
ps,
|
||||
&wh->c_hash,
|
||||
&pd))
|
||||
&wh->pd))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
return NULL;
|
||||
}
|
||||
TALER_denom_pub_deep_copy (&wh->pk.key,
|
||||
&pk->key);
|
||||
wh->wh2 = TALER_EXCHANGE_withdraw2 (exchange,
|
||||
&pd,
|
||||
reserve_priv,
|
||||
&wh->pd,
|
||||
wh->reserve_priv,
|
||||
&handle_reserve_withdraw_finished,
|
||||
wh);
|
||||
GNUNET_free (pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg);
|
||||
GNUNET_free (
|
||||
wh->pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg);
|
||||
return wh;
|
||||
case TALER_DENOMINATION_CS:
|
||||
struct TALER_WithdrawNonce nonce;
|
||||
TALER_cs_withdraw_nonce_derive (&ps->coin_priv, &nonce);
|
||||
TALER_cs_withdraw_nonce_derive (&ps->coin_priv,
|
||||
&wh->pd.blinded_planchet.details.
|
||||
cs_blinded_planchet.nonce);
|
||||
wh->csrh = TALER_EXCHANGE_csr (exchange,
|
||||
pk,
|
||||
&nonce,
|
||||
&wh->pd.blinded_planchet.details.
|
||||
cs_blinded_planchet.nonce,
|
||||
&withdraw_cs_stage_two_callback,
|
||||
wh);
|
||||
return wh;
|
||||
|
@ -437,11 +437,26 @@ TALER_EXCHANGE_withdraw2 (
|
||||
|
||||
TALER_amount_hton (&req.amount_with_fee,
|
||||
&wh->requested_amount);
|
||||
TALER_coin_ev_hash (
|
||||
pd->blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
|
||||
pd->blinded_planchet.details.rsa_blinded_planchet.
|
||||
blinded_msg_size,
|
||||
&req.h_coin_envelope);
|
||||
switch (dk->key.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
TALER_coin_ev_hash (
|
||||
pd->blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
|
||||
pd->blinded_planchet.details.rsa_blinded_planchet.
|
||||
blinded_msg_size,
|
||||
&req.h_coin_envelope);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
TALER_coin_ev_hash (
|
||||
&pd->blinded_planchet.details.cs_blinded_planchet,
|
||||
sizeof (pd->blinded_planchet.details.cs_blinded_planchet),
|
||||
&req.h_coin_envelope);
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
|
||||
&req,
|
||||
&reserve_sig.eddsa_signature);
|
||||
@ -449,17 +464,44 @@ TALER_EXCHANGE_withdraw2 (
|
||||
|
||||
{
|
||||
json_t *withdraw_obj;
|
||||
|
||||
withdraw_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
&pd->denom_pub_hash),
|
||||
GNUNET_JSON_pack_data_varsize ("coin_ev",
|
||||
pd->blinded_planchet.details.
|
||||
rsa_blinded_planchet.blinded_msg,
|
||||
pd->blinded_planchet.details.
|
||||
rsa_blinded_planchet.blinded_msg_size),
|
||||
GNUNET_JSON_pack_data_auto ("reserve_sig",
|
||||
&reserve_sig));
|
||||
switch (dk->key.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
withdraw_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
&pd->denom_pub_hash),
|
||||
GNUNET_JSON_pack_data_varsize ("coin_ev",
|
||||
pd->blinded_planchet.details.
|
||||
rsa_blinded_planchet.blinded_msg,
|
||||
pd->blinded_planchet.details.
|
||||
rsa_blinded_planchet.blinded_msg_size),
|
||||
GNUNET_JSON_pack_data_auto ("reserve_sig",
|
||||
&reserve_sig));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
json_t *coin_ev_object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("nonce",
|
||||
&pd->blinded_planchet.details.
|
||||
cs_blinded_planchet.nonce),
|
||||
GNUNET_JSON_pack_data_auto ("c0",
|
||||
&pd->blinded_planchet.details.
|
||||
cs_blinded_planchet.c[0]),
|
||||
GNUNET_JSON_pack_data_auto ("c1",
|
||||
&pd->blinded_planchet.details.
|
||||
cs_blinded_planchet.c[1]));
|
||||
withdraw_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
&pd->denom_pub_hash),
|
||||
GNUNET_JSON_pack_object_steal ("coin_ev",
|
||||
coin_ev_object),
|
||||
GNUNET_JSON_pack_data_auto ("reserve_sig",
|
||||
&reserve_sig));
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Attempting to withdraw from reserve %s\n",
|
||||
TALER_B2S (&wh->reserve_pub));
|
||||
|
@ -290,7 +290,9 @@ qconv_denom_sig (void *cls,
|
||||
denom_sig->details.rsa_signature,
|
||||
&tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
tlen = sizeof (denom_sig->details.cs_signature);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -307,7 +309,11 @@ qconv_denom_sig (void *cls,
|
||||
tlen);
|
||||
GNUNET_free (tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
&denom_sig->details.cs_signature,
|
||||
tlen);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -380,7 +386,9 @@ qconv_blinded_denom_sig (void *cls,
|
||||
denom_sig->details.blinded_rsa_signature,
|
||||
&tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
tlen = sizeof (denom_sig->details.blinded_cs_answer);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -397,7 +405,11 @@ qconv_blinded_denom_sig (void *cls,
|
||||
tlen);
|
||||
GNUNET_free (tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
&denom_sig->details.blinded_cs_answer,
|
||||
tlen);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
|
@ -670,7 +670,16 @@ extract_blinded_denom_sig (void *cls,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
// FIXME: add CS case!
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (sizeof (sig->details.blinded_cs_answer) != len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&sig->details.blinded_cs_answer,
|
||||
res,
|
||||
len);
|
||||
return GNUNET_OK;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
|
@ -413,49 +413,49 @@ run (void *cls,
|
||||
/**
|
||||
* Move money to the exchange's bank account.
|
||||
*/
|
||||
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
|
||||
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-cs-1",
|
||||
"EUR:6.02"),
|
||||
TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1",
|
||||
TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-cs-1",
|
||||
"EUR:6.02",
|
||||
bc.user42_payto,
|
||||
bc.exchange_payto,
|
||||
"create-reserve-1"),
|
||||
"create-reserve-cs-1"),
|
||||
/**
|
||||
* Make a reserve exist, according to the previous
|
||||
* transfer.
|
||||
*/
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-1"),
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-cs-1"),
|
||||
/**
|
||||
* Withdraw EUR:5.
|
||||
*/
|
||||
TALER_TESTING_cmd_withdraw_cs_amount ("withdraw-cs-coin-1",
|
||||
"create-reserve-1",
|
||||
"create-reserve-cs-1",
|
||||
"EUR:5",
|
||||
MHD_HTTP_OK),
|
||||
// TODO: rest of the tests
|
||||
// /**
|
||||
// * Withdraw EUR:1 using the SAME private coin key as for the previous coin
|
||||
// * (in violation of the specification, to be detected on spending!).
|
||||
// */
|
||||
// TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x",
|
||||
// "create-reserve-1",
|
||||
// "EUR:1",
|
||||
// "withdraw-coin-1",
|
||||
// MHD_HTTP_OK),
|
||||
// /**
|
||||
// * Check the reserve is depleted.
|
||||
// */
|
||||
// TALER_TESTING_cmd_status ("status-1",
|
||||
// "create-reserve-1",
|
||||
// "EUR:0",
|
||||
// MHD_HTTP_OK),
|
||||
// /*
|
||||
// * Try to overdraw.
|
||||
// */
|
||||
// TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
|
||||
// "create-reserve-1",
|
||||
// "EUR:5",
|
||||
// MHD_HTTP_CONFLICT),
|
||||
/**
|
||||
* Withdraw EUR:1 using the SAME private coin key as for the previous coin
|
||||
* (in violation of the specification, to be detected on spending!).
|
||||
*/
|
||||
TALER_TESTING_cmd_withdraw_cs_amount_reuse_key ("withdraw-cs-coin-1x",
|
||||
"create-reserve-cs-1",
|
||||
"EUR:1",
|
||||
"withdraw-cs-coin-1",
|
||||
MHD_HTTP_OK),
|
||||
/**
|
||||
* Check the reserve is depleted.
|
||||
*/
|
||||
TALER_TESTING_cmd_status ("status-cs-1",
|
||||
"create-reserve-cs-1",
|
||||
"EUR:0",
|
||||
MHD_HTTP_OK),
|
||||
/*
|
||||
* Try to overdraw.
|
||||
*/
|
||||
TALER_TESTING_cmd_withdraw_cs_amount ("withdraw-cs-coin-2",
|
||||
"create-reserve-cs-1",
|
||||
"EUR:5",
|
||||
MHD_HTTP_CONFLICT),
|
||||
// TODO: add test for nonce reuse
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
||||
|
@ -266,13 +266,6 @@ reserve_withdraw_cb (void *cls,
|
||||
switch (wr->hr.http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
// TODO: remove
|
||||
// temporary make test successful when CS
|
||||
if (TALER_DENOMINATION_CS == ws->cipher)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
TALER_denom_sig_deep_copy (&ws->sig,
|
||||
&wr->details.success.sig);
|
||||
if (0 != ws->total_backoff.rel_value_us)
|
||||
@ -661,6 +654,8 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
|
||||
const char *coin_ref,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
// TODO: ATM this is hardcoded to RSA denominations
|
||||
// (use TALER_TESTING_cmd_withdraw_cs_amount for Clause Schnorr)
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
cmd = TALER_TESTING_cmd_withdraw_amount (label,
|
||||
@ -676,6 +671,29 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_withdraw_cs_amount_reuse_key (
|
||||
const char *label,
|
||||
const char *reserve_reference,
|
||||
const char *amount,
|
||||
const char *coin_ref,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
cmd = TALER_TESTING_cmd_withdraw_cs_amount (label,
|
||||
reserve_reference,
|
||||
amount,
|
||||
expected_response_code);
|
||||
{
|
||||
struct WithdrawState *ws = cmd.cls;
|
||||
|
||||
ws->reuse_coin_key_ref = coin_ref;
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create withdraw command, letting the caller specify the
|
||||
* amount by a denomination key.
|
||||
|
Loading…
Reference in New Issue
Block a user