summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_withdraw.c
diff options
context:
space:
mode:
authorLucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>2022-01-08 20:41:01 +0100
committerGian Demarmels <gian@demarmels.org>2022-02-04 15:35:31 +0100
commit9074e66ebc8b73ecc98500f32af52088fd7f0722 (patch)
treee5e270bea1e2b3de44e915b428df01866a93203e /src/exchange/taler-exchange-httpd_withdraw.c
parent4c7aa097840eb3254a6823177abcc90fa7ccf0d0 (diff)
downloadexchange-9074e66ebc8b73ecc98500f32af52088fd7f0722.tar.gz
exchange-9074e66ebc8b73ecc98500f32af52088fd7f0722.tar.bz2
exchange-9074e66ebc8b73ecc98500f32af52088fd7f0722.zip
implement withdraw (nonce reuse check missing)
Diffstat (limited to 'src/exchange/taler-exchange-httpd_withdraw.c')
-rw-r--r--src/exchange/taler-exchange-httpd_withdraw.c164
1 files changed, 151 insertions, 13 deletions
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
index 53ba270ba..ed54fe278 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -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;