diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index e72c2ed61..84968582e 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -85,6 +85,12 @@ */ #define TALER_SIGNATURE_REFRESH_MELT_CONFIRM 9 +/** + * Signature where the Mint confirms a deposit request. + */ +#define TALER_SIGNATURE_MINT_DEPOSIT 10 + + /***********************/ /* Merchant signatures */ /***********************/ @@ -101,12 +107,12 @@ /** * Signature made by the wallet of a user to confirm a deposit permission */ -#define TALER_SIGNATURE_DEPOSIT 201 +#define TALER_SIGNATURE_WALLET_DEPOSIT 201 /** * Signature made by the wallet of a user to confirm a incremental deposit permission */ -#define TALER_SIGNATURE_INCREMENTAL_DEPOSIT 202 +#define TALER_SIGNATURE_INCREMENTAL_WALLET_DEPOSIT 202 @@ -149,7 +155,7 @@ struct TALER_WithdrawRequest struct TALER_DepositRequest { /** - * Purpose must be #TALER_SIGNATURE_DEPOSIT + * Purpose must be #TALER_SIGNATURE_WALLET_DEPOSIT */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; @@ -182,6 +188,51 @@ struct TALER_DepositRequest }; +/** + * Format used to generate the signature on a confirmation + * from the mint that a deposit request succeeded. + */ +struct TALER_DepositConfirmation +{ + /** + * Purpose must be #TALER_SIGNATURE_MINT_DEPOSIT + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Hash over the contract for which this deposit is made. + */ + struct GNUNET_HashCode h_contract; + + /** + * Hash over the wiring information of the merchant. + */ + struct GNUNET_HashCode h_wire; + + /** + * Merchant-generated transaction ID to detect duplicate + * transactions. + */ + uint64_t transaction_id GNUNET_PACKED; + + /** + * Amount to be deposited. + */ + struct TALER_AmountNBO amount; + + /** + * The coin's public key. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + + /** + * The Merachant's public key. + */ + struct GNUNET_CRYPTO_EddsaPublicKey merchant; + +}; + + /** * FIXME */ diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index cde603168..fb5ce4405 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -55,6 +55,11 @@ struct GNUNET_CONFIGURATION_Handle *cfg; */ struct GNUNET_CRYPTO_EddsaPublicKey master_pub; +/** + * Private key of the mint we use to sign messages. + */ +struct GNUNET_CRYPTO_EddsaPrivateKey mint_priv; + /** * The HTTP Daemon. */ @@ -223,7 +228,7 @@ handle_mhd_request (void *cls, * server into the corresponding global variables. * * @param param mint_directory the mint's directory - * @return GNUNET_OK on success + * @return #GNUNET_OK on success */ static int mint_serve_process_config (const char *mint_directory) @@ -231,6 +236,7 @@ mint_serve_process_config (const char *mint_directory) unsigned long long port; unsigned long long kappa; char *master_pub_str; + char *mint_priv_str; char *db_cfg; cfg = TALER_config_load (mint_directory); @@ -256,8 +262,30 @@ mint_serve_process_config (const char *mint_directory) { fprintf (stderr, "Invalid master public key given in mint configuration."); + GNUNET_free (master_pub_str); return GNUNET_NO; } + GNUNET_free (master_pub_str); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "mint", "mint_priv", + &mint_priv_str)) + { + fprintf (stderr, + "No master public key given in mint configuration."); + return GNUNET_NO; + } + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_private_key_from_string (mint_priv_str, + strlen (mint_priv_str), + &mint_priv)) + { + fprintf (stderr, + "Invalid mint private key given in mint configuration."); + GNUNET_free (mint_priv_str); + return GNUNET_NO; + } + GNUNET_free (mint_priv_str); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h index cff2859db..ed56b048d 100644 --- a/src/mint/taler-mint-httpd.h +++ b/src/mint/taler-mint-httpd.h @@ -48,6 +48,11 @@ extern char *mintdir; */ extern struct GNUNET_CRYPTO_EddsaPublicKey master_pub; +/** + * Private key of the mint we use to sign messages. + */ +extern struct GNUNET_CRYPTO_EddsaPrivateKey mint_priv; + /** * Struct describing an URL and the handler for it. diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index ee9f76d5d..0bd1134a6 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -60,7 +60,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, struct MintKeyState *key_state; struct TALER_DepositRequest dr; - dr.purpose.purpose = htonl (TALER_SIGNATURE_DEPOSIT); + dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT); dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); dr.h_contract = deposit->h_contract; dr.h_wire = deposit->h_wire; @@ -68,7 +68,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, dr.amount = TALER_amount_hton (deposit->amount); dr.coin_pub = deposit->coin.coin_pub; if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_DEPOSIT, + GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_WALLET_DEPOSIT, &dr.purpose, &deposit->csig, &deposit->coin.coin_pub)) @@ -101,8 +101,8 @@ verify_and_execute_deposit (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param root root of the posted JSON - * @param purpose is this a #TALER_SIGNATURE_DEPOSIT or - * #TALER_SIGNATURE_INCREMENTAL_DEPOSIT // FIXME: bad type, use enum! + * @param purpose is this a #TALER_SIGNATURE_WALLET_DEPOSIT or + * #TALER_SIGNATURE_INCREMENTAL_WALLET_DEPOSIT // FIXME: bad type, use enum! * @param amount how much should be deposited * @param wire json describing the wire details (?) * @return MHD result code @@ -258,9 +258,9 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh, } /* FIXME: use array search and enum, this is ugly */ if (0 == strcmp ("DIRECT_DEPOSIT", deposit_type)) - purpose = TALER_SIGNATURE_DEPOSIT; + purpose = TALER_SIGNATURE_WALLET_DEPOSIT; else if (0 == strcmp ("INCREMENTAL_DEPOSIT", deposit_type)) - purpose = TALER_SIGNATURE_INCREMENTAL_DEPOSIT; + purpose = TALER_SIGNATURE_INCREMENTAL_WALLET_DEPOSIT; else { GNUNET_break_op (0); diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 8a0d7e797..58addf98d 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -24,8 +24,6 @@ * @author Christian Grothoff * * TODO: - * - when generating /deposit reply, do include signature of mint - * to say that we accepted it (check reply format) * - when generating /withdraw/status reply, which signature do * we use there? Might want to instead return *all* signatures on the * existig withdraw operations, instead of Mint's signature @@ -275,14 +273,36 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *merchant, const struct TALER_Amount *amount) { - // FIXME: return more information here, - // including in particular a signature over - // the deposit data from the mint! - return TALER_MINT_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:s}", - "status", - "DEPOSIT_OK"); + struct TALER_DepositConfirmation dc; + struct GNUNET_CRYPTO_EddsaSignature sig; + json_t *sig_json; + int ret; + + dc.purpose.purpose = htonl (TALER_SIGNATURE_MINT_DEPOSIT); + dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmation)); + dc.h_contract = *h_contract; + dc.h_wire = *h_wire; + dc.transaction_id = GNUNET_htonll (transaction_id); + dc.amount = TALER_amount_hton (*amount); + dc.coin_pub = *coin_pub; + dc.merchant = *merchant; + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_sign (&mint_priv, + &dc.purpose, + &sig)) + { + LOG_WARNING ("Failed to create EdDSA signature using my private key\n"); + return TALER_MINT_reply_internal_error (connection, + "Failed to EdDSA-sign response\n"); + } + sig_json = TALER_JSON_from_sig (&dc.purpose, &sig); + ret = TALER_MINT_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:s, s:o}", + "status", "DEPOSIT_OK", + "signature", sig_json); + json_decref (sig_json); + return ret; } @@ -356,30 +376,32 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, const struct RefreshSession *session, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub) { - json_t *root; + int ret; json_t *list; struct GNUNET_HashContext *hash_context; struct RefreshMeltResponseSignatureBody body; struct GNUNET_CRYPTO_EddsaSignature sig; json_t *sig_json; - root = json_object (); list = json_array (); - json_object_set_new (root, "blind_session_pubs", list); hash_context = GNUNET_CRYPTO_hash_context_start (); body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); /* FIXME: should we not add something to the hash_context in the meantime? */ - GNUNET_CRYPTO_hash_context_finish (hash_context, &body.melt_response_hash); + GNUNET_CRYPTO_hash_context_finish (hash_context, + &body.melt_response_hash); TALER_MINT_keys_sign (&body.purpose, &sig); sig_json = TALER_JSON_from_sig (&body.purpose, &sig); GNUNET_assert (NULL != sig_json); - json_object_set (root, "signature", sig_json); - - return TALER_MINT_reply_json (connection, - root, - MHD_HTTP_OK); + ret = TALER_MINT_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o}", + "signature", sig_json, + "blind_session_pubs", list); + json_decref (sig_json); + json_decref (list); + return ret; } diff --git a/src/util/json.c b/src/util/json.c index d66c95c43..120e1be5c 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -112,7 +112,8 @@ TALER_JSON_from_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, el = json_integer ((json_int_t) ntohl (purpose->purpose)); json_object_set_new (root, "purpose", el); - el = TALER_JSON_from_data (signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)); + el = TALER_JSON_from_data (signature, + sizeof (struct GNUNET_CRYPTO_EddsaSignature)); json_object_set_new (root, "sig", el); return root;