diff options
author | Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch> | 2022-01-08 20:41:01 +0100 |
---|---|---|
committer | Gian Demarmels <gian@demarmels.org> | 2022-02-04 15:35:31 +0100 |
commit | 9074e66ebc8b73ecc98500f32af52088fd7f0722 (patch) | |
tree | e5e270bea1e2b3de44e915b428df01866a93203e /src/exchange/taler-exchange-httpd_withdraw.c | |
parent | 4c7aa097840eb3254a6823177abcc90fa7ccf0d0 (diff) | |
download | exchange-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.c | 164 |
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; |