From 82405b0ce5593b30a1b0ee1a1995f2214a71751c Mon Sep 17 00:00:00 2001 From: Lucien Heuzeveldt Date: Thu, 6 Jan 2022 15:55:50 +0100 Subject: implement CS key handling and csr endpoint --- src/lib/exchange_api_csr.c | 71 ++++++++++-------------- src/lib/exchange_api_management_get_keys.c | 22 ++++++++ src/lib/exchange_api_withdraw.c | 87 +++++++++++++++++++++++++----- 3 files changed, 123 insertions(+), 57 deletions(-) (limited to 'src/lib') diff --git a/src/lib/exchange_api_csr.c b/src/lib/exchange_api_csr.c index fa7010f2c..a3f631181 100644 --- a/src/lib/exchange_api_csr.c +++ b/src/lib/exchange_api_csr.c @@ -90,13 +90,16 @@ struct TALER_EXCHANGE_CsRHandle * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors */ static enum GNUNET_GenericReturnValue -csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh, - const json_t *json, +csr_ok (const json_t *json, struct TALER_EXCHANGE_CsRResponse *csrr) { struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_csr ("r_pub_0", &csrr->details.success.r_pubs.r_pub[0]), - TALER_JSON_spec_csr ("r_pub_1", &csrr->details.success.r_pubs.r_pub[1]), + GNUNET_JSON_spec_fixed ("r_pub_0", + &csrr->details.success.r_pubs.r_pub[0], + sizeof (struct GNUNET_CRYPTO_CsRPublic)), + GNUNET_JSON_spec_fixed ("r_pub_1", + &csrr->details.success.r_pubs.r_pub[1], + sizeof (struct GNUNET_CRYPTO_CsRPublic)), GNUNET_JSON_spec_end () }; @@ -109,37 +112,11 @@ csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh, return GNUNET_SYSERR; } - /* r_pubs are valid, return it to the application */ - csrh->cb (csrh->cb_cls, - csrr); - /* make sure callback isn't called again after return */ - csrh->cb = NULL; GNUNET_JSON_parse_free (spec); return GNUNET_OK; } -/** - * - * Cancel a CS R request. This function cannot be used - * on a request handle if a response is already served for it. - * - * @param csrh the withdraw handle - */ -void -TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh) -{ - if (NULL != csrh->job) - { - GNUNET_CURL_job_cancel (csrh->job); - csrh->job = NULL; - } - GNUNET_free (csrh->url); - TALER_curl_easy_post_finished (&csrh->post_ctx); - GNUNET_free (csrh); -} - - /** * Function called when we're done processing the HTTP /csr request. * @@ -170,8 +147,7 @@ handle_csr_finished (void *cls, break; case MHD_HTTP_OK: if (GNUNET_OK != - csr_ok (csrh, - j, + csr_ok (j, &csrr)) { GNUNET_break_op (0); @@ -179,9 +155,7 @@ handle_csr_finished (void *cls, csrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - GNUNET_assert (NULL == csrh->cb); - TALER_EXCHANGE_csr_cancel (csrh); - return; + break; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ @@ -190,8 +164,8 @@ handle_csr_finished (void *cls, break; case MHD_HTTP_NOT_FOUND: /* Nothing really to verify, the exchange basically just says - that it doesn't know the /csr. Can happen if the exchange - doesn't support Clause Schnorr. + that it doesn't know the /csr endpoint or denomination. + Can happen if the exchange doesn't support Clause Schnorr. We should simply pass the JSON reply to the application. */ csrr.hr.ec = TALER_JSON_get_error_code (j); csrr.hr.hint = TALER_JSON_get_error_hint (j); @@ -221,12 +195,9 @@ handle_csr_finished (void *cls, (int) hr.ec); break; } - if (NULL != csrh->cb) - { - csrh->cb (csrh->cb_cls, - &csrr); - csrh->cb = NULL; - } + csrh->cb (csrh->cb_cls, + &csrr); + csrh->cb = NULL; TALER_EXCHANGE_csr_cancel (csrh); } @@ -305,3 +276,17 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange, return csrh; } + + +void +TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh) +{ + if (NULL != csrh->job) + { + GNUNET_CURL_job_cancel (csrh->job); + csrh->job = NULL; + } + GNUNET_free (csrh->url); + TALER_curl_easy_post_finished (&csrh->post_ctx); + GNUNET_free (csrh); +} diff --git a/src/lib/exchange_api_management_get_keys.c b/src/lib/exchange_api_management_get_keys.c index e776082d3..4d6866338 100644 --- a/src/lib/exchange_api_management_get_keys.c +++ b/src/lib/exchange_api_management_get_keys.c @@ -92,6 +92,8 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh, &fk.master_pub), GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key", &fk.denom_secmod_public_key), + GNUNET_JSON_spec_fixed_auto ("denom_secmod_cs_public_key", + &fk.denom_secmod_cs_public_key), GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key", &fk.signkey_secmod_public_key), GNUNET_JSON_spec_end () @@ -243,6 +245,26 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh, } } break; + case TALER_DENOMINATION_CS: + { + struct TALER_CsPubHashP h_cs; + + TALER_cs_pub_hash (&denom_key->key.details.cs_public_key, + &h_cs); + if (GNUNET_OK != + TALER_exchange_secmod_cs_verify (&h_cs, + section_name, + denom_key->valid_from, + duration, + &fk.denom_secmod_cs_public_key, + &denom_key->denom_secmod_sig)) + { + GNUNET_break_op (0); + ok = false; + break; + } + } + break; default: GNUNET_break_op (0); ok = false; diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c index a8bce5e71..91838d4ce 100644 --- a/src/lib/exchange_api_withdraw.c +++ b/src/lib/exchange_api_withdraw.c @@ -73,6 +73,11 @@ struct TALER_EXCHANGE_WithdrawHandle */ struct TALER_CoinPubHash c_hash; + /** + * Handler for the CS R request (only used for TALER_DENOMINATION_CS denominations) + */ + struct TALER_EXCHANGE_CsRHandle *csrh; + }; @@ -147,6 +152,37 @@ handle_reserve_withdraw_finished ( } +/** + * Function called when stage 1 of CS withdraw is finished (request r_pub's) + * + * @param cls + */ +static void +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; + // } + + // TODO: this should only be called for non-OK cases + wh->cb (wh->cb_cls, + &wr); + TALER_EXCHANGE_withdraw_cancel (wh); +} + + /** * Withdraw a coin from the exchange using a /reserve/withdraw request. Note * that to ensure that no money is lost in case of hardware failures, @@ -183,31 +219,54 @@ TALER_EXCHANGE_withdraw ( wh->cb_cls = res_cb_cls; wh->pk = *pk; wh->ps = *ps; - if (GNUNET_OK != - TALER_planchet_prepare (&pk->key, - ps, - &wh->c_hash, - &pd)) + wh->csrh = NULL; + switch (pk->key.cipher) { + case TALER_DENOMINATION_RSA: + if (GNUNET_OK != + TALER_planchet_prepare (&pk->key, + ps, + &wh->c_hash, + &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, + &handle_reserve_withdraw_finished, + wh); + GNUNET_free (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); + wh->csrh = TALER_EXCHANGE_csr (exchange, + pk, + &nonce, + &withdraw_cs_stage_two_callback, + wh); + return wh; + default: 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, - &handle_reserve_withdraw_finished, - wh); - GNUNET_free (pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg); - return wh; } void TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh) { + if (NULL != wh->csrh) + { + TALER_EXCHANGE_csr_cancel (wh->csrh); + wh->csrh = NULL; + } if (NULL != wh->wh2) { TALER_EXCHANGE_withdraw2_cancel (wh->wh2); -- cgit v1.2.3