From f8c01f4b46a8391f3196889e5df7f8ebdfb6475d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 23 Jun 2020 11:00:23 +0200 Subject: implement signature verification on pay response --- src/lib/merchant_api_post_order_pay.c | 85 ++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 10 deletions(-) (limited to 'src/lib/merchant_api_post_order_pay.c') diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c index 650211c9..477c3a31 100644 --- a/src/lib/merchant_api_post_order_pay.c +++ b/src/lib/merchant_api_post_order_pay.c @@ -77,11 +77,29 @@ struct TALER_MERCHANT_OrderPayHandle */ struct TALER_MERCHANT_PaidCoin *coins; + /** + * Hash of the contract we are paying, set + * if @e am_wallet is true. + */ + struct GNUNET_HashCode h_contract_terms; + + /** + * Public key of the merchant (instance) being paid, set + * if @e am_wallet is true. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + /** * Number of @e coins we are paying with. */ unsigned int num_coins; + /** + * Set to true if this is the wallet API and we have + * initialized @e h_contract_terms and @e merchant_pub. + */ + bool am_wallet; + }; @@ -234,8 +252,45 @@ handle_pay_finished (void *cls, hr.ec = TALER_EC_INVALID_RESPONSE; break; case MHD_HTTP_OK: - // FIXME: should verify 'sig' from merchant here! - // FIXME: probably should return merchant signature to callback! + if (oph->am_wallet) + { + /* Here we can (and should) verify the merchant's signature */ + struct PaymentResponsePS pr = { + .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK), + .purpose.size = htonl (sizeof (pr)), + .h_contract_terms = oph->h_contract_terms + }; + struct TALER_MerchantSignatureP merchant_sig; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("sig", + &merchant_sig), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (json, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + hr.ec = TALER_EC_INVALID_RESPONSE; + hr.http_status = 0; + hr.hint = "sig field missing in response"; + break; + } + + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK, + &pr, + &merchant_sig.eddsa_sig, + &oph->merchant_pub.eddsa_pub)) + { + GNUNET_break_op (0); + hr.ec = TALER_EC_INVALID_RESPONSE; + hr.http_status = 0; + hr.hint = "signature invalid"; + } + } break; /* Tolerating Not Acceptable because sometimes * - especially in tests - we might want to POST @@ -623,14 +678,24 @@ TALER_MERCHANT_order_pay (struct GNUNET_CURL_Context *ctx, p->amount_without_fee = coin->amount_without_fee; p->exchange_url = coin->exchange_url; } - return TALER_MERCHANT_order_pay_frontend (ctx, - merchant_url, - order_id, - session_id, - num_coins, - pc, - pay_cb, - pay_cb_cls); + { + struct TALER_MERCHANT_OrderPayHandle *oph; + + oph = TALER_MERCHANT_order_pay_frontend (ctx, + merchant_url, + order_id, + session_id, + num_coins, + pc, + pay_cb, + pay_cb_cls); + if (NULL == oph) + return NULL; + oph->h_contract_terms = *h_contract_terms; + oph->merchant_pub = *merchant_pub; + oph->am_wallet = true; + return oph; + } } } -- cgit v1.2.3