diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/exchange_api_age_withdraw.c | 97 | ||||
-rw-r--r-- | src/lib/exchange_api_age_withdraw_reveal.c | 111 | ||||
-rw-r--r-- | src/lib/exchange_api_common.c | 2 | ||||
-rw-r--r-- | src/lib/notizen.md | 236 |
4 files changed, 282 insertions, 164 deletions
diff --git a/src/lib/exchange_api_age_withdraw.c b/src/lib/exchange_api_age_withdraw.c index b5da232e..c68fe67d 100644 --- a/src/lib/exchange_api_age_withdraw.c +++ b/src/lib/exchange_api_age_withdraw.c @@ -47,36 +47,9 @@ struct CoinCandidate struct TALER_PlanchetMasterSecretP secret; /** - * Age commitment for the coin candidates, calculated from the @e ps and a - * given maximum age + * The details derived form the master secrets */ - struct TALER_AgeCommitmentProof age_commitment_proof; - - /** - * Age commitment for the coin. - */ - struct TALER_AgeCommitmentHash h_age_commitment; - - /** - * blinding secret - */ - union TALER_DenominationBlindingKeyP blinding_key; - - /** - * Private key of the coin we are withdrawing. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; - - /** - * Values of the @cipher selected - */ - struct TALER_ExchangeWithdrawValues alg_values; - - /** - * Hash of the public key of the coin we are signing. - */ - struct TALER_CoinPubHashP h_coin_pub; - + struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails details; /** * Blinded hash of the coin @@ -340,11 +313,12 @@ reserve_age_withdraw_ok ( .hr.http_status = MHD_HTTP_OK, .details.ok.h_commitment = awbh->h_commitment }; + struct TALER_ExchangeSignatureP exchange_sig; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_uint8 ("noreaveal_index", &response.details.ok.noreveal_index), GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &response.details.ok.exchange_sig), + &exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &response.details.ok.exchange_pub) }; @@ -363,7 +337,7 @@ reserve_age_withdraw_ok ( &awbh->h_commitment, response.details.ok.noreveal_index, &response.details.ok.exchange_pub, - &response.details.ok.exchange_sig)) + &exchange_sig)) { GNUNET_break_op (0); return GNUNET_SYSERR; @@ -785,21 +759,26 @@ copy_results ( { struct TALER_EXCHANGE_AgeWithdrawHandle *awh = cls; uint8_t idx = awbr->details.ok.noreveal_index; - struct TALER_ExchangeWithdrawValues alg_values[awh->num_coins]; + struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails details[awh->num_coins]; + struct TALER_BlindedCoinHashP blinded_coin_hs[awh->num_coins]; struct TALER_EXCHANGE_AgeWithdrawResponse resp = { .hr = awbr->hr, .details = { .ok = { .noreveal_index = awbr->details.ok.noreveal_index, .h_commitment = awbr->details.ok.h_commitment, .exchange_pub = awbr->details.ok.exchange_pub, - .exchange_sig = awbr->details.ok.exchange_sig, - .num_alg_values = awh->num_coins, - .alg_values = alg_values}, + .num_coins = awh->num_coins, + .coin_details = details, + .blinded_coin_hs = blinded_coin_hs}, }, }; for (size_t n = 0; n< awh->num_coins; n++) - alg_values[n] = awh->coin_data[n].coin_candidates[idx].alg_values; + { + details[n] = awh->coin_data[n].coin_candidates[idx].details; + details[n].planchet = awh->coin_data[n].planchet_details[idx]; + blinded_coin_hs[n] = awh->coin_data[n].coin_candidates[idx].blinded_coin_h; + } awh->callback (awh->callback_cls, &resp); @@ -915,23 +894,23 @@ csr_withdraw_done ( { bool success = false; /* Complete the initialization of the coin with CS denomination */ - can->alg_values = csrr->details.ok.alg_values; + can->details.alg_values = csrr->details.ok.alg_values; TALER_planchet_setup_coin_priv (&can->secret, - &can->alg_values, - &can->coin_priv); + &can->details.alg_values, + &can->details.coin_priv); TALER_planchet_blinding_secret_create (&can->secret, - &can->alg_values, - &can->blinding_key); + &can->details.alg_values, + &can->details.blinding_key); /* This initializes the 2nd half of the can->planchet_detail.blinded_planchet! */ do { if (GNUNET_OK != TALER_planchet_prepare (&csr->denom_pub->key, - &can->alg_values, - &can->blinding_key, - &can->coin_priv, - &can->h_age_commitment, - &can->h_coin_pub, + &can->details.alg_values, + &can->details.blinding_key, + &can->details.coin_priv, + &can->details.h_age_commitment, + &can->details.h_coin_pub, planchet)) { GNUNET_break (0); @@ -1029,29 +1008,29 @@ prepare_coins ( &can->secret, &input->denom_pub->key.age_mask, awh->max_age, - &can->age_commitment_proof)); + &can->details.age_commitment_proof)); - TALER_age_commitment_hash (&can->age_commitment_proof.commitment, - &can->h_age_commitment); + TALER_age_commitment_hash (&can->details.age_commitment_proof.commitment, + &can->details.h_age_commitment); switch (input->denom_pub->key.cipher) { case TALER_DENOMINATION_RSA: { - can->alg_values.cipher = TALER_DENOMINATION_RSA; + can->details.alg_values.cipher = TALER_DENOMINATION_RSA; TALER_planchet_setup_coin_priv (&can->secret, - &can->alg_values, - &can->coin_priv); + &can->details.alg_values, + &can->details.coin_priv); TALER_planchet_blinding_secret_create (&can->secret, - &can->alg_values, - &can->blinding_key); + &can->details.alg_values, + &can->details.blinding_key); FAIL_IF (GNUNET_OK != TALER_planchet_prepare (&cd->denom_pub.key, - &can->alg_values, - &can->blinding_key, - &can->coin_priv, - &can->h_age_commitment, - &can->h_coin_pub, + &can->details.alg_values, + &can->details.blinding_key, + &can->details.coin_priv, + &can->details.h_age_commitment, + &can->details.h_coin_pub, planchet)); FAIL_IF (GNUNET_OK != TALER_coin_ev_hash (&planchet->blinded_planchet, diff --git a/src/lib/exchange_api_age_withdraw_reveal.c b/src/lib/exchange_api_age_withdraw_reveal.c index fcb551a9..75707a4e 100644 --- a/src/lib/exchange_api_age_withdraw_reveal.c +++ b/src/lib/exchange_api_age_withdraw_reveal.c @@ -47,19 +47,12 @@ struct TALER_EXCHANGE_AgeWithdrawRevealHandle /* The age-withdraw commitment */ struct TALER_AgeWithdrawCommitmentHashP h_commitment; - /* The maximum age */ - uint8_t max_age; - /* Number of coins */ size_t num_coins; /* The @e num_coins * kappa coin secrets from the age-withdraw commitment */ const struct TALER_EXCHANGE_AgeWithdrawCoinInput *coins_input; - /* The @e num_coins algorithm- and coin-specific parameters from the - * previous call to /age-withdraw. */ - const struct TALER_ExchangeWithdrawValues *alg_values; - /* The url for the reveal request */ const char *request_url; @@ -81,82 +74,6 @@ struct TALER_EXCHANGE_AgeWithdrawRevealHandle }; -static enum GNUNET_GenericReturnValue -reveal_coin ( - const struct TALER_PlanchetMasterSecretP *secret, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_ExchangeWithdrawValues *alg_values, - const struct TALER_BlindedDenominationSignature *blind_sig, - uint8_t max_age, - struct TALER_EXCHANGE_RevealedCoinInfo *revealed_coin) -{ - enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; - -#define BREAK_ON_FAILURE(call) \ - do { \ - if (GNUNET_OK != (call)) { GNUNET_break (0); break; } \ - } while(0) - - do { - struct TALER_CoinPubHashP h_coin_pub; - struct TALER_PlanchetDetail planchet_detail; - const struct TALER_AgeCommitmentHash *hac = NULL; - struct TALER_FreshCoin fresh_coin; - - TALER_planchet_setup_coin_priv (secret, - alg_values, - &revealed_coin->coin_priv); - - TALER_planchet_blinding_secret_create (secret, - alg_values, - &revealed_coin->bks); - - revealed_coin->age_commitment_proof = NULL; - if (0 < max_age) - { - BREAK_ON_FAILURE ( - TALER_age_restriction_from_secret ( - secret, - &denom_pub->age_mask, - max_age, - revealed_coin->age_commitment_proof)); - - TALER_age_commitment_hash ( - &revealed_coin->age_commitment_proof->commitment, - &revealed_coin->h_age_commitment); - - hac = &revealed_coin->h_age_commitment; - } - - BREAK_ON_FAILURE ( - TALER_planchet_prepare (denom_pub, - alg_values, - &revealed_coin->bks, - &revealed_coin->coin_priv, - hac, - &h_coin_pub, - &planchet_detail)); - - BREAK_ON_FAILURE ( - TALER_planchet_to_coin (denom_pub, - blind_sig, - &revealed_coin->bks, - &revealed_coin->coin_priv, - &revealed_coin->h_age_commitment, - &h_coin_pub, - alg_values, - &fresh_coin)); - - /* success */ - revealed_coin->sig = fresh_coin.sig; - ret = GNUNET_OK; - } while(0); - - return ret; -#undef BREAK_ON_FAILURE -} - - /** * We got a 200 OK response for the /age-withdraw/$ACH/reveal operation. * Extract the signed blindedcoins and return it to the caller. @@ -197,16 +114,14 @@ age_withdraw_reveal_ok ( } { - struct TALER_EXCHANGE_RevealedCoinInfo revealed_coins[awrh->num_coins]; + struct TALER_BlindedDenominationSignature denom_sigs[awrh->num_coins]; /* Reconstruct the coins and unblind the signatures */ for (size_t n = 0; n < awrh->num_coins; n++) { - enum GNUNET_GenericReturnValue ret; - struct TALER_BlindedDenominationSignature blinded_sig; json_t *j_sig = json_array_get (j_sigs, n); struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("", &blinded_sig), + GNUNET_JSON_spec_fixed_auto ("", &denom_sigs[n]), GNUNET_JSON_spec_end () }; @@ -218,19 +133,10 @@ age_withdraw_reveal_ok ( GNUNET_break_op (0); return GNUNET_SYSERR; } - ret = reveal_coin (&awrh->coins_input[n].secrets[awrh->noreveal_index], - &awrh->coins_input[n].denom_pub->key, - &awrh->alg_values[n], - &blinded_sig, - awrh->max_age, - &revealed_coins[n]); - - if (GNUNET_OK != ret) - return ret; } - response.details.ok.num_coins = awrh->num_coins; - response.details.ok.revealed_coins = revealed_coins; + response.details.ok.num_sigs = awrh->num_coins; + response.details.ok.blinded_denom_sigs = denom_sigs; awrh->callback (awrh->callback_cls, &response); /* Make sure the callback isn't called again */ @@ -510,24 +416,19 @@ TALER_EXCHANGE_age_withdraw_reveal ( size_t num_coins, const struct TALER_EXCHANGE_AgeWithdrawCoinInput coins_input[static num_coins], - const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], uint8_t noreveal_index, const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, - uint8_t max_age, TALER_EXCHANGE_AgeWithdrawRevealCallback reveal_cb, void *reveal_cb_cls) { struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh = GNUNET_new (struct TALER_EXCHANGE_AgeWithdrawRevealHandle); awrh->noreveal_index = noreveal_index; - awrh->callback = reveal_cb; - awrh->callback_cls = reveal_cb_cls; awrh->h_commitment = *h_commitment; awrh->num_coins = num_coins; awrh->coins_input = coins_input; - awrh->alg_values = alg_values; - awrh->max_age = max_age; - + awrh->callback = reveal_cb; + awrh->callback_cls = reveal_cb_cls; if (GNUNET_OK != prepare_url (exchange_url, diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 337fbaba..08ca4b4e 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -765,6 +765,8 @@ TALER_EXCHANGE_free_reserve_history ( break; case TALER_EXCHANGE_RTT_WITHDRAWAL: break; + case TALER_EXCHANGE_RTT_AGEWITHDRAWAL: + break; case TALER_EXCHANGE_RTT_RECOUP: break; case TALER_EXCHANGE_RTT_CLOSING: diff --git a/src/lib/notizen.md b/src/lib/notizen.md new file mode 100644 index 00000000..835fad9e --- /dev/null +++ b/src/lib/notizen.md @@ -0,0 +1,236 @@ +# Notes re: planchets and blinding + +## `TALER_denom_blind()` + +``` +Blind coin for blind signing with @a dk using blinding secret @a coin_bks. +``` + +- `@param[out] c_hash resulting hashed coin` +- `@param[out] blinded_planchet planchet data to initialize` + +## `TALER_planchet_prepare()` + +Prepare a planchet for withdrawal. Creates and blinds a coin. + +- calls `TALER_denom_blind()!` +- `@param[out] c_hash set to the hash of the public key of the coin (needed later)` +- `@param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and other withdraw operations, pd->blinded_planchet.cipher will be set to cipher from @a dk` + + +## `TALER_coin_ev_hash` + +Compute the hash of a blinded coin. + +- `@param blinded_planchet blinded planchet` +- `@param denom_hash hash of the denomination publick key` +- `@param[out] bch where to write the hash, type struct TALER_BlindedCoinHashP` + +**Where is this called!?** + +``` +taler-exchange-httpd_refreshes_reveal.c +605: TALER_coin_ev_hash (&rrc->blinded_planchet, + +taler-exchange-httpd_recoup.c +290: TALER_coin_ev_hash (&blinded_planchet, + +taler-exchange-httpd_withdraw.c +581: TALER_coin_ev_hash (&wc.blinded_planchet, + +taler-exchange-httpd_age-withdraw_reveal.c +350: ret = TALER_coin_ev_hash (&detail.blinded_planchet, + +taler-exchange-httpd_recoup-refresh.c +284: TALER_coin_ev_hash (&blinded_planchet, + +taler-exchange-httpd_age-withdraw.c +279: ret = TALER_coin_ev_hash (&awc->coin_evs[c], +884: TALER_coin_ev_hash (&awc->coin_evs[i], + +taler-exchange-httpd_batch-withdraw.c +832: TALER_coin_ev_hash (&pc->blinded_planchet, +``` + + +## `TALER_coin_pub_hash` + +Compute the hash of a coin. + +- `@param coin_pub public key of the coin` +- `@param age_commitment_hash hash of the age commitment vector. NULL, if no age commitment was set` +- `@param[out] coin_h where to write the hash` + +**Where is this called!?** + +### In `lib/crypto.c`, function `TALER_test_coin_valid`. + +``` +Check if a coin is valid; that is, whether the denomination key +exists, is not expired, and the signature is correct. + +@param coin_public_info the coin public info to check for validity +@param denom_pub denomination key, must match @a coin_public_info's `denom_pub_hash` +@return #GNUNET_YES if the coin is valid, + #GNUNET_NO if it is invalid + #GNUNET_SYSERR if an internal error occurred +``` + +It then calls `TALER_denom_pub_verify` on the result of `TALER_coin_pub_hash` and the signature + + +### In `util/denom.c`, function `TALER_denom_blind` + +## `TALER_EXCHANGE_batch_withdraw` vs `TALER_EXCHANGE_batch_withdraw2` + +### `TALER_EXCHANGE_batch_withdraw` + +``` +/** + * Withdraw multiple coins from the exchange using a /reserves/$RESERVE_PUB/batch-withdraw + * request. This API is typically used by a wallet to withdraw many coins from a + * reserve. + * + * Note that to ensure that no money is lost in case of hardware + * failures, the caller must have committed (most of) the arguments to + * disk before calling, and be ready to repeat the request with the + * same arguments in case of failures. + * + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange + * @param reserve_priv private key of the reserve to withdraw from + * @param wci_length number of entries in @a wcis + * @param wcis inputs that determine the planchets + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for @a res_cb + * @return NULL + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_BatchWithdrawHandle * +TALER_EXCHANGE_batch_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int wci_length, + const struct TALER_EXCHANGE_WithdrawCoinInput wcis[static wci_length], + TALER_EXCHANGE_BatchWithdrawCallback res_cb, + void *res_cb_cls); +``` + +### `TALER_EXCHANGE_batch_withdraw2` + +``` +/** + * Withdraw a coin from the exchange using a /reserves/$RESERVE_PUB/batch-withdraw + * request. This API is typically used by a merchant to withdraw a tip + * where the blinding factor is unknown to the merchant. + * + * Note that to ensure that no money is lost in case of hardware + * failures, the caller must have committed (most of) the arguments to + * disk before calling, and be ready to repeat the request with the + * same arguments in case of failures. + * + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange + * @param pds array of planchet details of the planchet to withdraw + * @param pds_length number of entries in the @a pds array + * @param reserve_priv private key of the reserve to withdraw from + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for @a res_cb + * @return NULL + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_BatchWithdraw2Handle * +TALER_EXCHANGE_batch_withdraw2 ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int pds_length, + const struct TALER_PlanchetDetail pds[static pds_length], + TALER_EXCHANGE_BatchWithdraw2Callback res_cb, + void *res_cb_cls); +``` + +### Differences + +| batch_withdraw | batch_withdraw2 | +|------------------------------------|------------------------| +| `TALER_EXCHANGE_WithdrawCoinInput` | `TALER_PlanchetDetail` | + + +``` +struct TALER_EXCHANGE_WithdrawCoinInput +{ + /** + * Denomination of the coin. + */ + const struct TALER_EXCHANGE_DenomPublicKey *pk; + + /** + * Master key material for the coin. + */ + const struct TALER_PlanchetMasterSecretP *ps; + + /** + * Age commitment for the coin. + */ + const struct TALER_AgeCommitmentHash *ach; + +}; +``` + + +``` +struct TALER_PlanchetDetail +{ + /** + * Hash of the denomination public key. + */ + struct TALER_DenominationHashP denom_pub_hash; + + /** + * The blinded planchet + */ + struct TALER_BlindedPlanchet { + /** + * Type of the sign blinded message + */ + enum TALER_DenominationCipher cipher; + + /** + * Details, depending on @e cipher. + */ + union + { + /** + * If we use #TALER_DENOMINATION_CS in @a cipher. + */ + struct TALER_BlindedCsPlanchet cs_blinded_planchet; + + /** + * If we use #TALER_DENOMINATION_RSA in @a cipher. + */ + struct TALER_BlindedRsaPlanchet rsa_blinded_planchet; + + } details; + } blinded_planchet; +}; + +``` + + + +## TODOs + +### Update documentation + +- [x] batch-withdraw needs error code for AgeRestrictionRequired +- [x] withdraw needs error code for AgeRestrictionRequired + + |