diff --git a/src/exchange/taler-exchange-httpd_reserves_purse.c b/src/exchange/taler-exchange-httpd_reserves_purse.c index a8ae8c1b3..620e83fc1 100644 --- a/src/exchange/taler-exchange-httpd_reserves_purse.c +++ b/src/exchange/taler-exchange-httpd_reserves_purse.c @@ -46,9 +46,9 @@ struct ReservePurseContext const struct TALER_ReservePublicKeyP *reserve_pub; /** - * Public key of the purse we are creating. + * Signature of the reserve affirming the merge. */ - struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_ReserveSignatureP reserve_sig; /** * Total amount to be put into the purse. @@ -70,11 +70,21 @@ struct ReservePurseContext */ struct TALER_PurseMergePublicKeyP merge_pub; + /** + * Merge affirmation by the @e merge_pub. + */ + struct TALER_PurseMergeSignatureP merge_sig; + /** * Contract decryption key for the purse. */ struct TALER_ContractDiffiePublicP contract_pub; + /** + * Public key of the purse we are creating. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + /** * Signature of the client affiming this request. */ @@ -252,7 +262,7 @@ purse_transaction (void *cls, return GNUNET_DB_STATUS_HARD_ERROR; } - /* 2) merge purse with reserve (and debit reserve) */ + /* 2) merge purse with reserve (and debit reserve for purse creation!) */ /* 3) if present, persist contract */ @@ -337,7 +347,7 @@ TEH_handler_reserves_purse ( json_t *deposit; unsigned int idx; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount ("amount", + TALER_JSON_spec_amount ("purse_value", TEH_currency, &rpc.amount), GNUNET_JSON_spec_uint32 ("min_age", @@ -357,14 +367,20 @@ TEH_handler_reserves_purse ( NULL), GNUNET_JSON_spec_fixed_auto ("merge_pub", &rpc.merge_pub), + GNUNET_JSON_spec_fixed_auto ("merge_sig", + &rpc.merge_sig), + GNUNET_JSON_spec_fixed_auto ("reserve_sig", + &rpc.reserve_sig), + GNUNET_JSON_spec_fixed_auto ("purse_pub", + &rpc.purse_pub), GNUNET_JSON_spec_fixed_auto ("purse_sig", &rpc.purse_sig), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &rpc.h_contract_terms), - GNUNET_JSON_spec_timestamp ("purse_expiration", - &rpc.purse_expiration), GNUNET_JSON_spec_timestamp ("merge_timestamp", &rpc.merge_timestamp), + GNUNET_JSON_spec_timestamp ("purse_expiration", + &rpc.purse_expiration), GNUNET_JSON_spec_end () }; const struct TEH_GlobalFee *gf; @@ -423,20 +439,53 @@ TEH_handler_reserves_purse ( TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; if (GNUNET_OK != - TALER_wallet_purse_purse_verify (rpc.purse_expiration, - &rpc.h_contract_terms, - &rpc.merge_pub, - rpc.min_age, - &rpc.amount, - rpc.purse_pub, - &rpc.purse_sig)) + TALER_wallet_purse_create_verify (rpc.purse_expiration, + &rpc.h_contract_terms, + &rpc.merge_pub, + rpc.min_age, + &rpc.amount, + rpc.purse_pub, + &rpc.purse_sig)) { - TALER_LOG_WARNING ("Invalid signature on /reserves/$PID/purse request\n"); + GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); GNUNET_free (rpc.coins); return TALER_MHD_reply_with_error (connection, MHD_HTTP_UNAUTHORIZED, - TALER_EC_EXCHANGE_PURSE_PURSE_SIGNATURE_INVALID, + TALER_EC_EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID, + NULL); + } + if (GNUNET_OK != + TALER_wallet_purse_merge_verify ("FIXME exchange_url", + rpc.merge_timestamp, + &rpc.purse_pub, + &rpc.merge_pub, + &rpc.merge_sig)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + GNUNET_free (rpc.coins); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_UNAUTHORIZED, + TALER_EC_EXCHANGE_PURSE_MERGE_SIGNATURE_INVALID, + NULL); + } + if (GNUNET_OK != + TALER_wallet_account_merge_verify (rpc.merge_timestamp, + &rpc.purse_pub, + rpc.purse_expiration, + &rpc.h_contract_terms, + &rpc.purse_value, + rpc.min_age, + rpc.reserve_pub, + &rpc.reserve_sig)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + GNUNET_free (rpc.coins); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_UNAUTHORIZED, + TALER_EC_EXCHANGE_RESERVE_MERGE_SIGNATURE_INVALID, NULL); } if ( (NULL != rpc.econtract) && diff --git a/src/lib/exchange_api_purse_create_with_merge.c b/src/lib/exchange_api_purse_create_with_merge.c index 226542b62..259e07db6 100644 --- a/src/lib/exchange_api_purse_create_with_merge.c +++ b/src/lib/exchange_api_purse_create_with_merge.c @@ -266,6 +266,8 @@ TALER_EXCHANGE_purse_create_with_merge ( uint32_t min_age = 0; struct TALER_PurseMergePublicKeyP merge_pub; struct TALER_PurseMergeSignatureP merge_sig; + struct TALER_ContractDiffiePublicP contract_pub; + struct TALER_PurseContractSignatureP contract_sig; void *econtract = NULL; size_t econtract_size = 0; @@ -291,6 +293,8 @@ TALER_EXCHANGE_purse_create_with_merge ( &pcm->reserve_pub.eddsa_pub); GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv, &merge_pub.eddsa_pub); + GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv, + &contract_pub.ecdhe_pub); // FIXME: extract min_age from contract_terms! @@ -347,26 +351,46 @@ TALER_EXCHANGE_purse_create_with_merge ( contract_terms, &econtract, &econtract_size); + TALER_wallet_econtract_upload_sign ( + econtract, + econtract_size, + &contract_pub, + purse_priv, + &contract_sig); } create_with_merge_obj = GNUNET_JSON_PACK ( + TALER_JSON_pack_amount ("purse_value", + purse_value_after_fees), + GNUNET_JSON_pack_data_uint64 ("min_age", + min_age), GNUNET_JSON_allow_null ( GNUNET_JSON_pack_data_varsize ("econtract", econtract, econtract_size)), + GNUNET_JSON_allow_null ( + upload_contract + ? GNUNET_JSON_pack_data_auto ("econtract_sig", + &contract_sig), + : GNUNET_JSON_pack_string ("dummy", + NULL)), + GNUNET_JSON_allow_null ( + upload_contract + ? GNUNET_JSON_pack_data_auto ("contract_pub", + &contract_pub), + : GNUNET_JSON_pack_string ("dummy", + NULL)), + GNUNET_JSON_pack_data_auto ("merge_pub", + &merge_pub), GNUNET_JSON_pack_data_auto ("merge_sig", &merge_sig), GNUNET_JSON_pack_data_auto ("reserve_sig", &reserve_sig), - GNUNET_JSON_pack_data_auto ("purse_sig", - &purse_sig), - GNUNET_JSON_pack_data_auto ("merge_pub", - &merge_pub), GNUNET_JSON_pack_data_auto ("purse_pub", &pcm->purse_pub), + GNUNET_JSON_pack_data_auto ("purse_sig", + &purse_sig), GNUNET_JSON_pack_data_auto ("h_contract_terms", &pcm->h_contract_terms), - TALER_JSON_pack_amount ("purse_value", - purse_value_after_fees), GNUNET_JSON_pack_timestamp ("merge_timestamp", merge_timestamp) GNUNET_JSON_pack_timestamp ("purse_expiration",