From 20c05dd5e3f0233cdf7291a05ec0348934dee652 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 31 Jan 2015 20:53:19 +0100 Subject: [PATCH] cleaning up /refresh/link logic, in particular separting out response generation logic --- src/mint/mint_db.c | 429 +++++++++++++++----------- src/mint/mint_db.h | 153 ++++++--- src/mint/taler-mint-httpd_db.c | 90 ++---- src/mint/taler-mint-httpd_responses.c | 66 ++++ src/mint/taler-mint-httpd_responses.h | 15 + 5 files changed, 450 insertions(+), 303 deletions(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 2b699928f..39b5a1514 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -60,7 +60,12 @@ static char *TALER_MINT_db_connection_cfg_str; } while (0) - +/** + * Setup prepared statements. + * + * @param db_conn connection handle to initialize + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ int TALER_MINT_DB_prepare (PGconn *db_conn) { @@ -494,189 +499,6 @@ TALER_MINT_DB_prepare (PGconn *db_conn) } -int -TALER_MINT_DB_set_commit_signature (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct GNUNET_CRYPTO_EddsaSignature *commit_sig) -{ - GNUNET_break (0); - return GNUNET_SYSERR; -} - - -int -TALER_db_get_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - LinkIterator link_iter, - void *cls) -{ - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(coin_pub), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_link", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - break_db_err (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - - - int i = 0; - int res; - - for (i = 0; i < PQntuples (result); i++) - { - struct TALER_RefreshLinkEncrypted *link_enc; - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - struct GNUNET_CRYPTO_rsa_Signature *sig; - char *ld_buf; - size_t ld_buf_size; - char *pk_buf; - size_t pk_buf_size; - char *sig_buf; - size_t sig_buf_size; - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC_VAR("link_vector_enc", &ld_buf, &ld_buf_size), - TALER_DB_RESULT_SPEC_VAR("denom_pub", &pk_buf, &pk_buf_size), - TALER_DB_RESULT_SPEC_VAR("ev_sig", &sig_buf, &sig_buf_size), - TALER_DB_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_DB_extract_result (result, rs, i)) - { - PQclear (result); - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (ld_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) - { - PQclear (result); - GNUNET_free (pk_buf); - GNUNET_free (sig_buf); - GNUNET_free (ld_buf); - GNUNET_break (0); - return GNUNET_SYSERR; - } - link_enc = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + - ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); - link_enc->blinding_key_enc = (const char *) &link_enc[1]; - link_enc->blinding_key_enc_size = ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); - memcpy (link_enc->coin_priv_enc, - ld_buf, - ld_buf_size); - - sig = GNUNET_CRYPTO_rsa_signature_decode (sig_buf, - sig_buf_size); - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (pk_buf, - pk_buf_size); - GNUNET_free (pk_buf); - GNUNET_free (sig_buf); - GNUNET_free (ld_buf); - if ( (NULL == sig) || - (NULL == denom_pub) ) - { - if (NULL != denom_pub) - GNUNET_CRYPTO_rsa_public_key_free (denom_pub); - if (NULL != sig) - GNUNET_CRYPTO_rsa_signature_free (sig); - GNUNET_free (link_enc); - GNUNET_break (0); - PQclear (result); - return GNUNET_SYSERR; - } - if (GNUNET_OK != (res = link_iter (cls, - link_enc, - denom_pub, - sig))) - { - GNUNET_assert (GNUNET_SYSERR != res); - GNUNET_CRYPTO_rsa_signature_free (sig); - GNUNET_CRYPTO_rsa_public_key_free (denom_pub); - GNUNET_free (link_enc); - PQclear (result); - return res; - } - GNUNET_CRYPTO_rsa_signature_free (sig); - GNUNET_CRYPTO_rsa_public_key_free (denom_pub); - GNUNET_free (link_enc); - } - - return GNUNET_OK; -} - - -int -TALER_db_get_transfer (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, - struct GNUNET_HashCode *shared_secret_enc) -{ - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(coin_pub), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_transfer", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - break_db_err (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - - if (1 != PQntuples (result)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "got %d tuples for get_transfer\n", - PQntuples (result)); - GNUNET_break (0); - return GNUNET_SYSERR; - } - - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("transfer_pub", transfer_pub), - TALER_DB_RESULT_SPEC("link_secret_enc", shared_secret_enc), - TALER_DB_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) - { - PQclear (result); - GNUNET_break (0); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - - - - -// Chaos -//////////////////////////////////////////////////////////////// -// Order - - - /** * Close thread-local database connection when a thread is destroyed. * @@ -1696,6 +1518,245 @@ TALER_MINT_DB_get_refresh_commit_link (PGconn *db_conn, } +/** + * Insert signature of a new coin generated during refresh into + * the database indexed by the refresh session and the index + * of the coin. This data is later used should an old coin + * be used to try to obtain the private keys during "/refresh/link". + * + * @param db_conn database connection + * @param session_pub refresh session + * @param newcoin_index coin index + * @param ev_sig coin signature + * @return #GNUNET_OK on success + */ +int +TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) +{ + // FIXME: check logic! + uint16_t newcoin_index_nbo = htons (newcoin_index); + char *buf; + size_t buf_size; + PGresult *result; + + buf_size = GNUNET_CRYPTO_rsa_signature_encode (ev_sig, + &buf); + { + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (db_conn, + "insert_refresh_collectable", + params); + } + GNUNET_free (buf); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + break_db_err (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Obtain the link data of a coin, that is the encrypted link + * information, the denomination keys and the signatures. + * + * @param db_conn database connection + * @param coin_pub public key to use to retrieve linkage data + * @return all known link data for the coin + */ +struct LinkDataList * +TALER_db_get_link (PGconn *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) +{ + struct LinkDataList *ldl; + struct LinkDataList *pos; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(coin_pub), + TALER_DB_QUERY_PARAM_END + }; + PGresult *result = TALER_DB_exec_prepared (db_conn, "get_link", params); + + ldl = NULL; + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + break_db_err (result); + PQclear (result); + return NULL; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + return NULL; + } + + + int i = 0; + + for (i = 0; i < PQntuples (result); i++) + { + struct TALER_RefreshLinkEncrypted *link_enc; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct GNUNET_CRYPTO_rsa_Signature *sig; + char *ld_buf; + size_t ld_buf_size; + char *pk_buf; + size_t pk_buf_size; + char *sig_buf; + size_t sig_buf_size; + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC_VAR("link_vector_enc", &ld_buf, &ld_buf_size), + TALER_DB_RESULT_SPEC_VAR("denom_pub", &pk_buf, &pk_buf_size), + TALER_DB_RESULT_SPEC_VAR("ev_sig", &sig_buf, &sig_buf_size), + TALER_DB_RESULT_SPEC_END + }; + + if (GNUNET_OK != TALER_DB_extract_result (result, rs, i)) + { + PQclear (result); + GNUNET_break (0); + TALER_db_link_data_list_free (ldl); + return NULL; + } + if (ld_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) + { + PQclear (result); + GNUNET_free (pk_buf); + GNUNET_free (sig_buf); + GNUNET_free (ld_buf); + TALER_db_link_data_list_free (ldl); + return NULL; + } + // FIXME: use util API for this! + link_enc = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + + ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); + link_enc->blinding_key_enc = (const char *) &link_enc[1]; + link_enc->blinding_key_enc_size = ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); + memcpy (link_enc->coin_priv_enc, + ld_buf, + ld_buf_size); + + sig = GNUNET_CRYPTO_rsa_signature_decode (sig_buf, + sig_buf_size); + denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (pk_buf, + pk_buf_size); + GNUNET_free (pk_buf); + GNUNET_free (sig_buf); + GNUNET_free (ld_buf); + if ( (NULL == sig) || + (NULL == denom_pub) ) + { + if (NULL != denom_pub) + GNUNET_CRYPTO_rsa_public_key_free (denom_pub); + if (NULL != sig) + GNUNET_CRYPTO_rsa_signature_free (sig); + GNUNET_free (link_enc); + GNUNET_break (0); + PQclear (result); + TALER_db_link_data_list_free (ldl); + return NULL; + } + pos = GNUNET_new (struct LinkDataList); + pos->next = ldl; + pos->link_data_enc = link_enc; + pos->denom_pub = denom_pub; + pos->ev_sig = sig; + ldl = pos; + } + return ldl; +} + + +/** + * Free memory of the link data list. + * + * @param ldl link data list to release + */ +void +TALER_db_link_data_list_free (struct LinkDataList *ldl) +{ + GNUNET_break (0); // FIXME +} + + +/** + * Obtain shared secret and transfer public key from the public key of + * the coin. This information and the link information returned by + * #TALER_db_get_link() enable the owner of an old coin to determine + * the private keys of the new coins after the melt. + * + * + * @param db_conn database connection + * @param coin_pub public key of the coin + * @param transfer_pub[OUT] public transfer key + * @param shared_secret_enc[OUT] set to shared secret + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure (not found) + * #GNUNET_SYSERR on internal failure (database issue) + */ +int +TALER_db_get_transfer (PGconn *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + struct TALER_EncryptedLinkSecret *shared_secret_enc) +{ + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(coin_pub), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (db_conn, "get_transfer", params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + break_db_err (result); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_NO; + } + + if (1 != PQntuples (result)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "got %d tuples for get_transfer\n", + PQntuples (result)); + GNUNET_break (0); + return GNUNET_SYSERR; + } + + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC("transfer_pub", transfer_pub), + TALER_DB_RESULT_SPEC("link_secret_enc", shared_secret_enc), + TALER_DB_RESULT_SPEC_END + }; + + if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) + { + PQclear (result); + GNUNET_break (0); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 658e87e46..6d82afd16 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -28,56 +28,11 @@ #include "taler_util.h" -/** - * FIXME. - */ -int -TALER_MINT_DB_prepare (PGconn *db_conn); - - - - - - -/** - * FIXME: doc, name is bad, too. - */ -typedef int -(*LinkIterator) (void *cls, - const struct TALER_RefreshLinkEncrypted *link_data_enc, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, - const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); - - -int -TALER_db_get_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - LinkIterator link_iter, - void *cls); - - -/** - * Obtain shared secret from the transfer public key (?). - * - * @param shared_secret_enc[out] set to shared secret; FIXME: use other type - * to indicate this is the encrypted secret - */ -int -TALER_db_get_transfer (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, - struct GNUNET_HashCode *shared_secret_enc); - - - -// Chaos -//////////////////////////////////////////////////////////////// -// Order - - - /** * Initialize database subsystem. + * + * @param connection_cfg configuration for the DB + * @return #GNUNET_OK on success */ int TALER_MINT_DB_init (const char *connection_cfg); @@ -93,6 +48,17 @@ PGconn * TALER_MINT_DB_get_connection (void); +/** + * Setup prepared statements. FIXME: should this be part of the API, + * or just internal to "TALER_MINT_DB_get_connection()"? + * + * @param db_conn connection handle to initialize + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ +int +TALER_MINT_DB_prepare (PGconn *db_conn); + + /** * Start a transaction. * @@ -711,6 +677,97 @@ TALER_MINT_DB_get_refresh_commit_link (PGconn *db_conn, struct RefreshCommitLink *cc); +/** + * Insert signature of a new coin generated during refresh into + * the database indexed by the refresh session and the index + * of the coin. This data is later used should an old coin + * be used to try to obtain the private keys during "/refresh/link". + * + * @param db_conn database connection + * @param session_pub refresh session + * @param newcoin_index coin index + * @param ev_sig coin signature + * @return #GNUNET_OK on success + */ +int +TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); + + +/** + * Linked list of refresh information linked to a coin. + */ +struct LinkDataList +{ + /** + * Information is stored in a NULL-terminated linked list. + */ + struct LinkDataList *next; + + /** + * Link data, used to recover the private key of the coin + * by the owner of the old coin. + */ + struct TALER_RefreshLinkEncrypted *link_data_enc; + + /** + * Denomination public key, determines the value of the coin. + */ + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + + /** + * Signature over the blinded envelope. + */ + struct GNUNET_CRYPTO_rsa_Signature *ev_sig; +}; + + +/** + * Obtain the link data of a coin, that is the encrypted link + * information, the denomination keys and the signatures. + * + * @param db_conn database connection + * @param coin_pub public key to use to retrieve linkage data + * @return all known link data for the coin + */ +struct LinkDataList * +TALER_db_get_link (PGconn *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + + +/** + * Free memory of the link data list. + * + * @param ldl link data list to release + */ +void +TALER_db_link_data_list_free (struct LinkDataList *ldl); + + +/** + * Obtain shared secret and transfer public key from the public key of + * the coin. This information and the link information returned by + * #TALER_db_get_link() enable the owner of an old coin to determine + * the private keys of the new coins after the melt. + * + * + * @param db_conn database connection + * @param coin_pub public key of the coin + * @param transfer_pub[OUT] public transfer key + * @param shared_secret_enc[OUT] set to shared secret + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure (not found) + * #GNUNET_SYSERR on internal failure (database issue) + */ +int +TALER_db_get_transfer (PGconn *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + struct TALER_EncryptedLinkSecret *shared_secret_enc); + + /** * Specification for a /lock operation. */ diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index d213f3bb1..cd51b58af 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -988,6 +988,16 @@ refresh_mint_coin (struct MHD_Connection *connection, GNUNET_break (0); return NULL; } + if (GNUNET_OK != + TALER_MINT_DB_insert_refresh_collectable (db_conn, + refresh_session, + coin_off, + ev_sig)) + { + GNUNET_break (0); + GNUNET_CRYPTO_rsa_signature_free (ev_sig); + return NULL; + } return ev_sig; } @@ -1173,47 +1183,6 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, } - -/** - * FIXME: move into response generation logic! - * FIXME: need to separate this from DB logic! - */ -static int -link_iter (void *cls, - const struct TALER_RefreshLinkEncrypted *link_data_enc, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, - const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) -{ - json_t *list = cls; - json_t *obj = json_object (); - char *buf; - size_t buf_len; - - - json_array_append_new (list, obj); - - json_object_set_new (obj, "link_enc", - TALER_JSON_from_data (link_data_enc->coin_priv_enc, - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) + - link_data_enc->blinding_key_enc_size)); - - buf_len = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, - &buf); - json_object_set_new (obj, "denom_pub", - TALER_JSON_from_data (buf, - buf_len)); - GNUNET_free (buf); - buf_len = GNUNET_CRYPTO_rsa_signature_encode (ev_sig, - &buf); - json_object_set_new (obj, "ev_sig", - TALER_JSON_from_data (buf, - buf_len)); - GNUNET_free (buf); - - return GNUNET_OK; -} - - /** * Execute a "/refresh/link". Returns the linkage information that * will allow the owner of a coin to follow the refresh trail to @@ -1228,18 +1197,16 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) { int res; - json_t *root; - json_t *list; PGconn *db_conn; struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; - struct GNUNET_HashCode shared_secret_enc; + struct TALER_EncryptedLinkSecret shared_secret_enc; + struct LinkDataList *ldl; if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - res = TALER_db_get_transfer (db_conn, coin_pub, &transfer_pub, @@ -1259,21 +1226,8 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection, } GNUNET_assert (GNUNET_OK == res); - /* FIXME: separate out response generation logic! */ - - list = json_array (); - root = json_object (); - json_object_set_new (root, "new_coins", list); - - res = TALER_db_get_link (db_conn, coin_pub, - &link_iter, list); - if (GNUNET_SYSERR == res) - { - GNUNET_break (0); - // FIXME: return error code! - return MHD_NO; - } - if (GNUNET_NO == res) + ldl = TALER_db_get_link (db_conn, coin_pub); + if (NULL == ldl) { return TALER_MINT_reply_json_pack (connection, MHD_HTTP_NOT_FOUND, @@ -1281,17 +1235,11 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection, "error", "link data not found (link)"); } - GNUNET_assert (GNUNET_OK == res); - json_object_set_new (root, "transfer_pub", - TALER_JSON_from_data (&transfer_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); - json_object_set_new (root, "secret_enc", - TALER_JSON_from_data (&shared_secret_enc, - sizeof (struct GNUNET_HashCode))); - res = TALER_MINT_reply_json (connection, - root, - MHD_HTTP_OK); - json_decref (root); + res = TALER_MINT_reply_refresh_link_success (connection, + &transfer_pub, + &shared_secret_enc, + ldl); + TALER_db_link_data_list_free (ldl); return res; } diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 264e5a126..4a920c08b 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -647,5 +647,71 @@ TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, } +/** + * Send a response for "/refresh/link". + * + * @param connection the connection to send the response to + * @param transfer_pub transfer public key + * @param shared_secret_enc encrypted shared secret + * @param ldl linked list with link data + * @return a MHD result code + */ +int +TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, + const struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + const struct TALER_EncryptedLinkSecret *shared_secret_enc, + const struct LinkDataList *ldl) +{ + const struct LinkDataList *pos; + json_t *root; + json_t *list; + int res; + + list = json_array (); + for (pos = ldl; NULL != pos; pos = pos->next) + { + json_t *obj; + char *buf; + size_t buf_len; + + obj = json_object (); + json_object_set_new (obj, "link_enc", + TALER_JSON_from_data (ldl->link_data_enc->coin_priv_enc, + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) + + ldl->link_data_enc->blinding_key_enc_size)); + buf_len = GNUNET_CRYPTO_rsa_public_key_encode (ldl->denom_pub, + &buf); + json_object_set_new (obj, "denom_pub", + TALER_JSON_from_data (buf, + buf_len)); + GNUNET_free (buf); + buf_len = GNUNET_CRYPTO_rsa_signature_encode (ldl->ev_sig, + &buf); + json_object_set_new (obj, "ev_sig", + TALER_JSON_from_data (buf, + buf_len)); + GNUNET_free (buf); + json_array_append_new (list, obj); + } + + root = json_object (); + json_object_set_new (root, + "new_coins", + list); + json_object_set_new (root, + "transfer_pub", + TALER_JSON_from_data (transfer_pub, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); + json_object_set_new (root, + "secret_enc", + TALER_JSON_from_data (shared_secret_enc, + sizeof (struct TALER_EncryptedLinkSecret))); + res = TALER_MINT_reply_json (connection, + root, + MHD_HTTP_OK); + json_decref (root); + return res; +} + /* end of taler-mint-httpd_responses.c */ diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index c6f31f1dc..24fb2ef8a 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -292,5 +292,20 @@ TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, struct GNUNET_CRYPTO_rsa_Signature **sigs); +/** + * Send a response for "/refresh/link". + * + * @param connection the connection to send the response to + * @param transfer_pub transfer public key + * @param shared_secret_enc encrypted shared secret + * @param ldl linked list with link data + * @return a MHD result code + */ +int +TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, + const struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + const struct TALER_EncryptedLinkSecret *shared_secret_enc, + const struct LinkDataList *ldl); + #endif