diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/taler_merchant_service.h | 64 | ||||
-rw-r--r-- | src/lib/merchant_api_post_order_pay.c | 75 |
2 files changed, 138 insertions, 1 deletions
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 057c9eff..180df516 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -3201,6 +3201,38 @@ struct TALER_MERCHANT_PaidCoin /** + * Information the frontend forwards to the backend to use a token for + * an order. Note that this does not include the token use private key, + * but only public keys and signatures. + */ +struct TALER_MERCHANT_UsedToken +{ + + /** + * Signature on TALER_TokenUseRequestPS made with the token use private key. + */ + struct TALER_TokenUseSignatureP token_sig; + + /** + * Public key of the token. This was blindly signed by the merchant + * during the issuance and is now being revealed to the merchant. + */ + struct TALER_TokenUsePublicKeyP token_pub; + + /** + * Unblinded signature made by the token issue public key of the merchant. + */ + struct TALER_TokenIssueSignatureP ub_sig; + + /** + * Token issue public key associated with this token. + */ + struct TALER_TokenIssuePublicKeyP issue_pub; + +}; + + +/** * Pay a merchant. API for frontends talking to backends. Here, * the frontend does not have the coin's private keys, but just * the public keys and signatures. @@ -3215,6 +3247,8 @@ struct TALER_MERCHANT_PaidCoin * @param wallet_data inputs from the wallet for the contract, NULL for none * @param num_coins length of the @a coins array * @param coins array of coins to pay with + * @param num_tokens length of the @a tokens array + * @param tokens array of tokens used * @param pay_cb the callback to call when a reply for this request is available * @param pay_cb_cls closure for @a pay_cb * @return a handle for this request @@ -3228,6 +3262,8 @@ TALER_MERCHANT_order_pay_frontend ( const json_t *wallet_data, unsigned int num_coins, const struct TALER_MERCHANT_PaidCoin coins[static num_coins], + unsigned int num_tokens, + const struct TALER_MERCHANT_UsedToken tokens[static num_tokens], TALER_MERCHANT_OrderPayCallback pay_cb, void *pay_cb_cls); @@ -3282,6 +3318,30 @@ struct TALER_MERCHANT_PayCoin /** + * Information we need from the wallet to use a token for an order. + */ +struct TALER_MERCHANT_UseToken +{ + + /** + * Token use private key. We will derive the public key from this. + */ + struct TALER_TokenUsePrivateKeyP token_priv; + + /** + * Unblinded signature made by the token issue public key of the merchant. + */ + struct TALER_TokenIssueSignatureP ub_sig; + + /** + * Token issue public key associated with this token. + */ + struct TALER_TokenIssuePublicKeyP issue_pub; + +}; + + +/** * Pay a merchant. API for wallets that have the coin's private keys. * * This is a PUBLIC API for wallets. @@ -3302,6 +3362,8 @@ struct TALER_MERCHANT_PayCoin * @param order_id order id * @param num_coins number of coins used to pay * @param coins array of coins we use to pay + * @param num_tokens number of tokens to used in this payment request + * @param tokens array of tokens we use in this payment request * @param pay_cb the callback to call when a reply for this request is available * @param pay_cb_cls closure for @a pay_cb * @return a handle for this request @@ -3324,6 +3386,8 @@ TALER_MERCHANT_order_pay ( const char *order_id, unsigned int num_coins, const struct TALER_MERCHANT_PayCoin coins[static num_coins], + unsigned int num_tokens, + const struct TALER_MERCHANT_UseToken tokens[static num_tokens], TALER_MERCHANT_OrderPayCallback pay_cb, void *pay_cb_cls); diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c index 57c85565..e56bac60 100644 --- a/src/lib/merchant_api_post_order_pay.c +++ b/src/lib/merchant_api_post_order_pay.c @@ -80,6 +80,11 @@ struct TALER_MERCHANT_OrderPayHandle struct TALER_MERCHANT_PaidCoin *coins; /** + * The tokens we are using. + */ + struct TALER_MERCHANT_UsedToken *tokens; + + /** * Hash of the contract we are paying, set * if @e am_wallet is true. */ @@ -114,6 +119,11 @@ struct TALER_MERCHANT_OrderPayHandle unsigned int num_coins; /** + * Number of @e tokens we are using. + */ + unsigned int num_tokens; + + /** * Set to true if this is the wallet API and we have * initialized @e h_contract_terms and @e merchant_pub. */ @@ -308,12 +318,15 @@ TALER_MERCHANT_order_pay_frontend ( const json_t *wallet_data, unsigned int num_coins, const struct TALER_MERCHANT_PaidCoin coins[static num_coins], + unsigned int num_tokens, + const struct TALER_MERCHANT_UsedToken tokens[static num_tokens], TALER_MERCHANT_OrderPayCallback pay_cb, void *pay_cb_cls) { struct TALER_MERCHANT_OrderPayHandle *oph; json_t *pay_obj; json_t *j_coins; + json_t *j_tokens = NULL; CURL *eh; struct TALER_Amount total_fee; struct TALER_Amount total_amount; @@ -392,10 +405,43 @@ TALER_MERCHANT_order_pay_frontend ( } } + if (0 < num_tokens) + { + j_tokens = json_array (); + GNUNET_assert (NULL != j_tokens); + for (unsigned int i = 0; i<num_tokens; i++) + { + json_t *j_token; + const struct TALER_MERCHANT_UsedToken *ut = &tokens[i]; + + j_token = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ("token_sig", + &ut->token_sig), + GNUNET_JSON_pack_data_auto ("token_pub", + &ut->token_pub), + TALER_JSON_pack_token_issue_sig ("ub_sig", + &ut->ub_sig), + /* TODO: Check if we need a more specific hash, similar to TALER_denom_pub_hash () */ + GNUNET_JSON_pack_data_auto ("h_issue", + &ut->issue_pub.public_key->pub_key_hash)); + if (0 != + json_array_append_new (j_tokens, + j_token)) + { + GNUNET_break (0); + json_decref (j_tokens); + return NULL; + } + } + } + pay_obj = GNUNET_JSON_PACK ( GNUNET_JSON_pack_array_steal ("coins", j_coins), GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_array_steal ("tokens", + j_tokens)), + GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_object_incref ("wallet_data", (json_t *) wallet_data)), GNUNET_JSON_pack_allow_null ( @@ -473,11 +519,13 @@ TALER_MERCHANT_order_pay ( const char *order_id, unsigned int num_coins, const struct TALER_MERCHANT_PayCoin coins[static num_coins], + unsigned int num_tokens, + const struct TALER_MERCHANT_UseToken tokens[static num_tokens], TALER_MERCHANT_OrderPayCallback pay_cb, void *pay_cb_cls) { struct GNUNET_HashCode wallet_data_hash; - + if (GNUNET_YES != TALER_amount_cmp_currency (amount, max_fee)) @@ -485,11 +533,20 @@ TALER_MERCHANT_order_pay ( GNUNET_break (0); return NULL; } + if (0 < num_tokens && NULL == wallet_data) + { + /* Since the wallet has to sign over the wallet_data_hash + to use tokens, wallet data must not be NULL if input + tokens are provided */ + GNUNET_break (0); + return NULL; + } if (NULL != wallet_data) TALER_json_hash (wallet_data, &wallet_data_hash); { struct TALER_MERCHANT_PaidCoin pc[num_coins]; + struct TALER_MERCHANT_UsedToken ut[num_tokens]; for (unsigned int i = 0; i<num_coins; i++) { @@ -534,6 +591,20 @@ TALER_MERCHANT_order_pay ( p->amount_without_fee = coin->amount_without_fee; p->exchange_url = coin->exchange_url; } + for (unsigned int i = 0; i<num_tokens; i++) + { + const struct TALER_MERCHANT_UseToken *token = &tokens[i]; + struct TALER_MERCHANT_UsedToken *t = &ut[i]; + + TALER_wallet_token_use_sign (h_contract_terms, + &wallet_data_hash, // checked for != NULL above + &token->token_priv, + &t->token_sig); + t->ub_sig = token->ub_sig; + t->issue_pub = token->issue_pub; + GNUNET_CRYPTO_eddsa_key_get_public (&token->token_priv.private_key, + &t->token_pub.public_key); + } { struct TALER_MERCHANT_OrderPayHandle *oph; @@ -544,6 +615,8 @@ TALER_MERCHANT_order_pay ( wallet_data, num_coins, pc, + num_tokens, + ut, pay_cb, pay_cb_cls); if (NULL == oph) |