diff options
-rw-r--r-- | src/exchange/taler-exchange-httpd_csr.c | 4 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_keys.c | 14 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_withdraw.c | 164 | ||||
-rw-r--r-- | src/include/taler_testing_lib.h | 24 | ||||
-rw-r--r-- | src/json/json_helper.c | 24 | ||||
-rw-r--r-- | src/json/json_pack.c | 21 | ||||
-rw-r--r-- | src/lib/exchange_api_withdraw.c | 88 | ||||
-rw-r--r-- | src/lib/exchange_api_withdraw2.c | 74 | ||||
-rw-r--r-- | src/pq/pq_query_helper.c | 20 | ||||
-rw-r--r-- | src/pq/pq_result_helper.c | 11 | ||||
-rw-r--r-- | src/testing/test_exchange_api.c | 58 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_withdraw.c | 32 |
12 files changed, 425 insertions, 109 deletions
diff --git a/src/exchange/taler-exchange-httpd_csr.c b/src/exchange/taler-exchange-httpd_csr.c index 0e330fe30..415dc7acf 100644 --- a/src/exchange/taler-exchange-httpd_csr.c +++ b/src/exchange/taler-exchange-httpd_csr.c @@ -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; diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index dd5928fb9..66c0f69e2 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -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; 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; diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index d5746c5c8..c6bebbeef 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -1333,6 +1333,30 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key ( /** + * 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. * diff --git a/src/json/json_helper.c b/src/json/json_helper.c index c07129d1a..6ee9c15a7 100644 --- a/src/json/json_helper.c +++ b/src/json/json_helper.c @@ -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; diff --git a/src/json/json_pack.c b/src/json/json_pack.c index 869867189..cc147c4c0 100644 --- a/src/json/json_pack.c +++ b/src/json/json_pack.c @@ -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); } diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c index 91838d4ce..2c57797fd 100644 --- a/src/lib/exchange_api_withdraw.c +++ b/src/lib/exchange_api_withdraw.c @@ -59,11 +59,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. */ struct TALER_EXCHANGE_DenomPublicKey pk; @@ -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; diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c index c8eb31822..cb767e434 100644 --- a/src/lib/exchange_api_withdraw2.c +++ b/src/lib/exchange_api_withdraw2.c @@ -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)); diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c index c04161d0e..ca1e94efb 100644 --- a/src/pq/pq_query_helper.c +++ b/src/pq/pq_query_helper.c @@ -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); } diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c index d6b0eb7bb..2009f0e33 100644 --- a/src/pq/pq_result_helper.c +++ b/src/pq/pq_result_helper.c @@ -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); } diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c index 29a3e5c6f..ba293d4b9 100644 --- a/src/testing/test_exchange_api.c +++ b/src/testing/test_exchange_api.c @@ -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 () }; diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c index e07eac341..2a98765f4 100644 --- a/src/testing/testing_api_cmd_withdraw.c +++ b/src/testing/testing_api_cmd_withdraw.c @@ -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. |