diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-01-29 20:00:21 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-01-29 20:00:21 +0100 |
commit | 090ddf170bd6fcf1d3d3d9d4fcc720ccb86b089e (patch) | |
tree | 3fc2f500c96db57fdb6cff4c68f9d93bcf5e4389 | |
parent | 8ca555500f01ebb2f7286961588b81b4ee5ac4fe (diff) |
working on cleaning up /refresh/melt logic
-rw-r--r-- | src/include/taler_signatures.h | 39 | ||||
-rw-r--r-- | src/mint/mint.h | 48 | ||||
-rw-r--r-- | src/mint/mint_db.c | 237 | ||||
-rw-r--r-- | src/mint/mint_db.h | 116 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 151 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 6 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 3 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 26 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.h | 10 |
9 files changed, 367 insertions, 269 deletions
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 84968582e..0518af3f0 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -234,6 +234,36 @@ struct TALER_DepositConfirmation /** + * Format of the block signed by the Mint in response to + * a successful "/refresh/melt" request. Hereby the mint + * affirms that all of the coins were successfully melted. + */ +struct RefreshMeltResponseSignatureBody +{ + /** + * Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE. + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Signature of the client over the melt request (thereby + * indirectly including all of the information the client + * sent). + */ + struct GNUNET_CRYPTO_EddsaSignature melt_client_signature; + + /** + * Public key of the refresh session for which + * @e melt_client_signature must be a valid signature. + */ + struct GNUNET_CRYPTO_EddsaPublicKey session_key; +}; + + + + + +/** * FIXME */ struct TALER_MINT_SignKeyIssue @@ -296,15 +326,6 @@ struct RefreshCommitResponseSignatureBody }; -/** - * FIXME - */ -struct RefreshMeltResponseSignatureBody -{ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - struct GNUNET_HashCode melt_response_hash; -}; - /** * FIXME diff --git a/src/mint/mint.h b/src/mint/mint.h index 1e1221157..e2d559701 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h @@ -36,54 +36,6 @@ -/** - * Global information for a refreshing session. - */ -struct RefreshSession -{ - /** - * Signature over the commitments by the client. - */ - struct GNUNET_CRYPTO_EddsaSignature commit_sig; - - /** - * Public key of the refreshing session, used to sign - * the client's commit message. - */ - struct GNUNET_CRYPTO_EddsaPublicKey session_pub; - - /** - * Number of coins we are melting. - */ - uint16_t num_oldcoins; - - /** - * Number of new coins we are creating. - */ - uint16_t num_newcoins; - - /** - * Number of parallel operations we perform for the cut and choose. - * (must be greater or equal to three for security). - */ - uint16_t kappa; - - /** - * Index (smaller @e kappa) which the mint has chosen to not - * have revealed during cut and choose. - */ - uint16_t noreveal_index; - - /** - * FIXME. - */ - int has_commit_sig; - - /** - * FIXME. - */ - uint8_t reveal_ok; -}; diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 5c52948e6..67cf4b352 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -582,76 +582,6 @@ TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, int -TALER_MINT_DB_get_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - struct RefreshSession *session) -{ - int res; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_session", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Query failed: %s\n", - PQresultErrorMessage (result)); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - return GNUNET_NO; - - GNUNET_assert (1 == PQntuples (result)); - - /* We're done if the caller is only interested in - * whether the session exists or not */ - - if (NULL == session) - return GNUNET_YES; - - memset (session, 0, sizeof (struct RefreshSession)); - - session->session_pub = *refresh_session_pub; - - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("num_oldcoins", &session->num_oldcoins), - TALER_DB_RESULT_SPEC("num_newcoins", &session->num_newcoins), - TALER_DB_RESULT_SPEC("kappa", &session->kappa), - TALER_DB_RESULT_SPEC("noreveal_index", &session->noreveal_index), - TALER_DB_RESULT_SPEC("reveal_ok", &session->reveal_ok), - TALER_DB_RESULT_SPEC_END - }; - - res = TALER_DB_extract_result (result, rs, 0); - - if (GNUNET_OK != res) - { - GNUNET_break (0); - PQclear (result); - return GNUNET_SYSERR; - } - - if (TALER_DB_field_isnull (result, 0, "session_commit_sig")) - session->has_commit_sig = GNUNET_NO; - else - session->has_commit_sig = GNUNET_YES; - - session->num_oldcoins = ntohs (session->num_oldcoins); - session->num_newcoins = ntohs (session->num_newcoins); - session->kappa = ntohs (session->kappa); - session->noreveal_index = ntohs (session->noreveal_index); - - PQclear (result); - return GNUNET_YES; -} - - -int TALER_MINT_DB_get_known_coin (PGconn *db_conn, const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, struct KnownCoin *known_coin) @@ -744,34 +674,6 @@ TALER_MINT_DB_get_known_coin (PGconn *db_conn, int -TALER_MINT_DB_create_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub) -{ - uint16_t noreveal_index; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), - TALER_DB_QUERY_PARAM_PTR(&noreveal_index), - TALER_DB_QUERY_PARAM_END - }; - - noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15); - noreveal_index = htonl (noreveal_index); - - PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_session", params); - - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - break_db_err (result); - PQclear (result); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -int TALER_MINT_DB_set_commit_signature (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, const struct GNUNET_CRYPTO_EddsaSignature *commit_sig) @@ -1882,6 +1784,145 @@ TALER_MINT_DB_insert_deposit (PGconn *db_conn, /** + * Lookup refresh session data under the given public key. + * + * @param db_conn database handle to use + * @param refresh_session_pub public key to use for the lookup + * @param session[OUT] where to store the result + * @return #GNUNET_YES on success, + * #GNUNET_NO if not found, + * #GNUNET_SYSERR on DB failure + */ +int +TALER_MINT_DB_get_refresh_session (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct RefreshSession *session) +{ + // FIXME: check logic! + int res; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_session", params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Query failed: %s\n", + PQresultErrorMessage (result)); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 == PQntuples (result)) + return GNUNET_NO; + + GNUNET_assert (1 == PQntuples (result)); + + /* We're done if the caller is only interested in + * whether the session exists or not */ + + if (NULL == session) + return GNUNET_YES; + + memset (session, 0, sizeof (struct RefreshSession)); + + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC("num_oldcoins", &session->num_oldcoins), + TALER_DB_RESULT_SPEC("num_newcoins", &session->num_newcoins), + TALER_DB_RESULT_SPEC("kappa", &session->kappa), + TALER_DB_RESULT_SPEC("noreveal_index", &session->noreveal_index), + TALER_DB_RESULT_SPEC_END + }; + + res = TALER_DB_extract_result (result, rs, 0); + + if (GNUNET_OK != res) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + if (TALER_DB_field_isnull (result, 0, "session_commit_sig")) + session->has_commit_sig = GNUNET_NO; + else + session->has_commit_sig = GNUNET_YES; + + session->num_oldcoins = ntohs (session->num_oldcoins); + session->num_newcoins = ntohs (session->num_newcoins); + session->kappa = ntohs (session->kappa); + session->noreveal_index = ntohs (session->noreveal_index); + + PQclear (result); + return GNUNET_YES; +} + + +/** + * Store new refresh session data under the given public key. + * + * @param db_conn database handle to use + * @param refresh_session_pub public key to use to locate the session + * @param session session data to store + * @return #GNUNET_YES on success, + * #GNUNET_SYSERR on DB failure + */ +int +TALER_MINT_DB_create_refresh_session (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct RefreshSession *session) +{ + // FIXME: actually store session data! + uint16_t noreveal_index; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(&noreveal_index), + TALER_DB_QUERY_PARAM_END + }; + + noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15); + noreveal_index = htonl (noreveal_index); + + PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_session", params); + + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + break_db_err (result); + PQclear (result); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Update new refresh session with the new state after the + * /refresh/commit operation. + * + * @param db_conn database handle to use + * @param refresh_session_pub public key to use to locate the session + * @param noreveal_index index chosen for the client to not reveal + * @param commit_client_sig signature of the client over its commitment + * @return #GNUNET_YES on success, + * #GNUNET_SYSERR on DB failure + */ +int +TALER_MINT_DB_update_refresh_session (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t noreveal_index, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig) +{ + // FIXME: implement! + return GNUNET_SYSERR; +} + + +/** * Test if the given /refresh/melt request is known to us. * * @param db_conn database connection diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 57b74f46e..e53df8ac2 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -44,10 +44,9 @@ TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); -int -TALER_MINT_DB_get_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - struct RefreshSession *r_session); + + + /** @@ -86,10 +85,6 @@ TALER_MINT_DB_insert_known_coin (PGconn *db_conn, const struct KnownCoin *known_coin); -int -TALER_MINT_DB_create_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); - /** * Store the commitment to the given (encrypted) refresh link data @@ -521,10 +516,111 @@ TALER_MINT_DB_insert_deposit (PGconn *db_conn, const struct Deposit *deposit); + +/** + * Global information for a refreshing session. Includes + * dimensions of the operation, security parameters and + * client signatures from "/refresh/melt" and "/refresh/commit". + */ +struct RefreshSession +{ + /** + * Signature over the commitments by the client, + * only valid if @e has_commit_sig is set. + */ + struct GNUNET_CRYPTO_EddsaSignature commit_sig; + + /** + * Signature over the melt by the client. + */ + struct GNUNET_CRYPTO_EddsaSignature melt_sig; + + /** + * Number of coins we are melting. + */ + uint16_t num_oldcoins; + + /** + * Number of new coins we are creating. + */ + uint16_t num_newcoins; + + /** + * Number of parallel operations we perform for the cut and choose. + * (must be greater or equal to three for security). 0 if not yet + * known. + */ + uint16_t kappa; + + /** + * Index (smaller @e kappa) which the mint has chosen to not + * have revealed during cut and choose. Only valid if + * @e has_commit_sig is set to #GNUNET_YES. + */ + uint16_t noreveal_index; + + /** + * #GNUNET_YES if we have accepted the /refresh/commit and + * thus the @e commit_sig is valid. + */ + int has_commit_sig; + +}; + + +/** + * Lookup refresh session data under the given public key. + * + * @param db_conn database handle to use + * @param refresh_session_pub public key to use for the lookup + * @param session[OUT] where to store the result + * @return #GNUNET_YES on success, + * #GNUNET_NO if not found, + * #GNUNET_SYSERR on DB failure + */ +int +TALER_MINT_DB_get_refresh_session (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct RefreshSession *session); + + +/** + * Store new refresh session data under the given public key. + * + * @param db_conn database handle to use + * @param refresh_session_pub public key to use to locate the session + * @param session session data to store + * @return #GNUNET_YES on success, + * #GNUNET_SYSERR on DB failure + */ +int +TALER_MINT_DB_create_refresh_session (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct RefreshSession *session); + + +/** + * Update new refresh session with the new state after the + * /refresh/commit operation. + * + * @param db_conn database handle to use + * @param refresh_session_pub public key to use to locate the session + * @param noreveal_index index chosen for the client to not reveal + * @param commit_client_sig signature of the client over its commitment + * @return #GNUNET_YES on success, + * #GNUNET_SYSERR on DB failure + */ +int +TALER_MINT_DB_update_refresh_session (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t noreveal_index, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig); + + /** - * Specification for a /refresh/melt operation. + * Specification for coin in a /refresh/melt operation. */ -struct RefreshMelt +struct RefreshMelt /* FIXME: name to make it clearer this is about ONE coin! */ { /** * Information about the coin that is being melted. diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index eae37199b..2f6ca0137 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -602,6 +602,8 @@ refresh_accept_melts (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param refresh_session_pub public key of the refresh session + * @param client_signature signature of the client (matching @a refresh_session_pub) + * over the melting request * @param num_new_denoms number of entries in @a denom_pubs * @param denum_pubs public keys of the coins we want to withdraw in the end * @param coin_count number of entries in @a coin_public_infos @@ -611,6 +613,7 @@ refresh_accept_melts (struct MHD_Connection *connection, int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct GNUNET_CRYPTO_EddsaSignature *client_signature, unsigned int num_new_denoms, struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, unsigned int coin_count, @@ -622,57 +625,48 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, PGconn *db_conn; int res; - /* We incrementally update the db with other parameters in a transaction. - * The transaction is aborted if some parameter does not validate. */ - - /* Send response immediately if we already know the session. - * Do _not_ care about fields other than session_pub in this case. */ - if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } + if (GNUNET_OK != + TALER_MINT_DB_transaction (db_conn)) + { + GNUNET_break (0); + return TALER_MINT_reply_internal_db_error (connection); + } res = TALER_MINT_DB_get_refresh_session (db_conn, refresh_session_pub, - NULL); + &session); if (GNUNET_YES == res) { - if (GNUNET_OK != - (res = TALER_MINT_DB_get_refresh_session (db_conn, - refresh_session_pub, - &session))) - { - // FIXME: send internal error - GNUNET_break (0); - return MHD_NO; - } + TALER_MINT_DB_rollback (db_conn); return TALER_MINT_reply_refresh_melt_success (connection, - &session, + &session.melt_sig, refresh_session_pub); } if (GNUNET_SYSERR == res) { - // FIXME: return 'internal error'? - GNUNET_break (0); - return MHD_NO; + TALER_MINT_DB_rollback (db_conn); + return TALER_MINT_reply_internal_db_error (connection); } - if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) - { - GNUNET_break (0); - return TALER_MINT_reply_internal_db_error (connection); - } - if (GNUNET_OK != TALER_MINT_DB_create_refresh_session (db_conn, - refresh_session_pub)) + session.melt_sig = *client_signature; + session.num_oldcoins = coin_count; + session.num_newcoins = num_new_denoms; + session.kappa = 0; /* FIXME: should be chosen by mint per config! */ + session.noreveal_index = UINT16_MAX; + session.has_commit_sig = GNUNET_NO; + if (GNUNET_OK != + (res = TALER_MINT_DB_create_refresh_session (db_conn, + refresh_session_pub, + &session))) { - // FIXME: return 'internal error'? - GNUNET_break (0); TALER_MINT_DB_rollback (db_conn); - return MHD_NO; + return TALER_MINT_reply_internal_db_error (connection); } /* The next two operations must see the same key state, @@ -725,7 +719,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, return MHD_NO; } return TALER_MINT_reply_refresh_melt_success (connection, - &session, + client_signature, refresh_session_pub); @@ -741,6 +735,8 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * @a kappa sets of private transfer keys should not be revealed. * * @param connection the MHD connection to handle + * @param refresh_session public key of the session + * @param commit_client_sig signature of the client over this commitment * @param kappa size of x-dimension of @commit_coin and @commit_link arrays * @param num_oldcoins size of y-dimension of @commit_link array * @param num_newcoins size of y-dimension of @commit_coin array @@ -754,6 +750,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, int TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, unsigned int kappa, unsigned int num_oldcoins, unsigned int num_newcoins, @@ -773,12 +770,35 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } - /* Send response immediately if we already know the session. - * Do _not_ care about fields other than session_pub in this case. */ - + if (GNUNET_OK != + TALER_MINT_DB_transaction (db_conn)) + { + GNUNET_break (0); + return TALER_MINT_reply_internal_db_error (connection); + } res = TALER_MINT_DB_get_refresh_session (db_conn, refresh_session_pub, &refresh_session); + if (GNUNET_SYSERR == res) + { + TALER_MINT_DB_rollback (db_conn); + return TALER_MINT_reply_internal_db_error (connection); + } + if (GNUNET_NO == res) + { + TALER_MINT_DB_rollback (db_conn); + return TALER_MINT_reply_arg_invalid (connection, + "session_pub"); + } + if (GNUNET_YES == refresh_session.has_commit_sig) + { + TALER_MINT_DB_rollback (db_conn); + res = TALER_MINT_reply_refresh_commit_success (connection, + &refresh_session); + return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; + } + + // FIXME: this should check that kappa and num_newcoins match // our expectations from refresh_session! @@ -814,47 +834,20 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, } } - - - - - if ( (GNUNET_YES == res) && - (GNUNET_YES == refresh_session.has_commit_sig) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "sending cached commit response\n"); - res = TALER_MINT_reply_refresh_commit_success (connection, - &refresh_session); - GNUNET_break (res != GNUNET_SYSERR); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - if (GNUNET_SYSERR == res) - { - // FIXME: return 'internal error'? - GNUNET_break (0); - return MHD_NO; - } + refresh_session.noreveal_index + = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, + refresh_session.kappa); if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) + (res = TALER_MINT_DB_update_refresh_session (db_conn, + refresh_session_pub, + refresh_session.noreveal_index, + commit_client_sig))) { - GNUNET_break (0); + TALER_MINT_DB_rollback (db_conn); return TALER_MINT_reply_internal_db_error (connection); } - /* Re-fetch the session information from the database, - * in case a concurrent transaction modified it. */ - - res = TALER_MINT_DB_get_refresh_session (db_conn, - refresh_session_pub, - &refresh_session); - if (GNUNET_OK != res) - { - // FIXME: return 'internal error'? - GNUNET_break (GNUNET_SYSERR != res); - TALER_MINT_DB_rollback (db_conn); - return MHD_NO; - } if (GNUNET_OK != TALER_MINT_DB_commit (db_conn)) @@ -943,24 +936,14 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } - /* Send response immediately if we already know the session, - * and the session commited already. - * Do _not_ care about fields other than session_pub in this case. */ - res = TALER_MINT_DB_get_refresh_session (db_conn, refresh_session_pub, &refresh_session); - if (GNUNET_YES == res && 0 != refresh_session.reveal_ok) - return helper_refresh_reveal_send_response (connection, - db_conn, - &refresh_session, - refresh_session_pub); + if (GNUNET_NO == res) + return TALER_MINT_reply_arg_invalid (connection, + "session_pub"); if (GNUNET_SYSERR == res) - { - GNUNET_break (0); - // FIXME: return 'internal error'? - return MHD_NO; - } + return TALER_MINT_reply_internal_db_error (connection); /* Check that the transfer private keys match their commitments. * Then derive the shared secret for each kappa, and check that they match. */ diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index e53d1b8ef..4b9aa1fe0 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -91,6 +91,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param refresh_session_pub public key of the refresh session + * @param client_signature signature of the client (matching @a refresh_session_pub) + * over the melting request * @param num_new_denoms number of entries in @a denom_pubs * @param denum_pubs array of public denomination keys for the refresh (?) * @param coin_count number of entries in @a coin_public_infos @@ -100,6 +102,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct GNUNET_CRYPTO_EddsaSignature *client_signature, unsigned int num_new_denoms, struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, unsigned int coin_count, @@ -115,6 +118,8 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * @a kappa sets of private transfer keys should not be revealed. * * @param connection the MHD connection to handle + * @param refresh_session public key of the session + * @param commit_client_sig signature of the client over this commitment * @param kappa size of x-dimension of @commit_coin and @commit_link arrays * @param num_oldcoins size of y-dimension of @commit_coin array * @param num_newcoins size of y-dimension of @commit_link array @@ -129,6 +134,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, int TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, unsigned int kappa, unsigned int num_oldcoins, unsigned int num_newcoins, diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index e7497327b..1267ca48b 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -242,8 +242,10 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, "error", "value mismatch"); } + /* FIXME: we must also store the signature over the melt! (#3635) */ return TALER_MINT_db_execute_refresh_melt (connection, refresh_session_pub, + NULL, /* FIXME: #3635! */ num_new_denoms, denom_pubs, coin_count, @@ -715,6 +717,7 @@ handle_refresh_commit_json (struct MHD_Connection *connection, /* FIXME: we must also store the signature! (#3635) */ res = TALER_MINT_db_execute_refresh_commit (connection, refresh_session_pub, + NULL /* FIXME: 3635! */, kappa, num_oldcoins, num_newcoins, diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 892b92ca7..de0736bdc 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -518,43 +518,37 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, /** - * Send a response for "/refresh/melt". + * Send a response for "/refresh/melt". Essentially we sign + * over the client's signature and public key, thereby + * demonstrating that we accepted all of the client's coins. * * @param connection the connection to send the response to - * @param db_conn the database connection to fetch values from + * @param signature the client's signature over the melt request * @param session_pub the refresh session public key. * @return a MHD result code */ int TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, - const struct RefreshSession *session, + const struct GNUNET_CRYPTO_EddsaSignature *signature, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub) { int ret; - json_t *list; - struct GNUNET_HashContext *hash_context; struct RefreshMeltResponseSignatureBody body; struct GNUNET_CRYPTO_EddsaSignature sig; json_t *sig_json; - list = json_array (); - 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); + body.melt_client_signature = *signature; + body.session_key = *session_pub; TALER_MINT_keys_sign (&body.purpose, &sig); sig_json = TALER_JSON_from_sig (&body.purpose, &sig); - GNUNET_assert (NULL != sig_json); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, - "{s:o, s:o}", - "signature", sig_json, - "blind_session_pubs", list); + "{s:o}", + "signature", sig_json); json_decref (sig_json); - json_decref (list); return ret; } @@ -570,7 +564,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, */ int TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, - struct RefreshSession *refresh_session) + const struct RefreshSession *refresh_session) { struct RefreshCommitResponseSignatureBody body; struct GNUNET_CRYPTO_EddsaSignature sig; diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index ebe1038fd..6cf934094 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -245,20 +245,22 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, */ int TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, - struct RefreshSession *refresh_session); + const struct RefreshSession *refresh_session); /** - * Send a response for "/refresh/melt". + * Send a response for "/refresh/melt". Essentially we sign + * over the client's signature and public key, thereby + * demonstrating that we accepted all of the client's coins. * * @param connection the connection to send the response to - * @param session session data to generate reply from + * @param signature the client's signature over the melt request * @param session_pub the refresh session public key. * @return a MHD result code */ int TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, - const struct RefreshSession *session, + const struct GNUNET_CRYPTO_EddsaSignature *signature, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); |