finished first pass over /refresh/reveal logic, simplifying mint_db API by keeping sigs around immediately

This commit is contained in:
Christian Grothoff 2015-01-31 20:08:21 +01:00
parent 6d8ccc9fe7
commit 2bb962c9be
3 changed files with 132 additions and 278 deletions

View File

@ -504,126 +504,6 @@ TALER_MINT_DB_set_commit_signature (PGconn *db_conn,
}
int
TALER_MINT_DB_set_reveal_ok (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
{
struct TALER_DB_QueryParam params[] = {
TALER_DB_QUERY_PARAM_PTR(session_pub),
TALER_DB_QUERY_PARAM_END
};
PGresult *result = TALER_DB_exec_prepared (db_conn, "set_reveal_ok", params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
break_db_err (result);
PQclear (result);
return GNUNET_SYSERR;
}
if (0 != strcmp ("1", PQcmdTuples (result)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
PQclear (result);
return GNUNET_OK;
}
int
TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn,
uint16_t newcoin_index,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
const struct GNUNET_CRYPTO_rsa_Signature *ev_sig)
{
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;
}
struct GNUNET_CRYPTO_rsa_Signature *
TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn,
uint16_t newcoin_index,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
{
struct GNUNET_CRYPTO_rsa_Signature *ev_sig;
char *buf;
size_t buf_size;
uint16_t newcoin_index_nbo = htons (newcoin_index);
struct TALER_DB_QueryParam params[] = {
TALER_DB_QUERY_PARAM_PTR(session_pub),
TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
TALER_DB_QUERY_PARAM_END
};
PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_collectable", params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
break_db_err (result);
PQclear (result);
return NULL;
}
if (0 == PQntuples (result))
{
PQclear (result);
/* FIXME: may want to distinguish between different error cases! */
return NULL;
}
GNUNET_assert (1 == PQntuples (result));
struct TALER_DB_ResultSpec rs[] = {
TALER_DB_RESULT_SPEC_VAR("ev_sig", &buf, &buf_size),
TALER_DB_RESULT_SPEC_END
};
if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
{
PQclear (result);
GNUNET_break (0);
return NULL;
}
PQclear (result);
ev_sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
buf_size);
GNUNET_free (buf);
return ev_sig;
}
int
TALER_db_get_link (PGconn *db_conn,
const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,

View File

@ -36,24 +36,6 @@ TALER_MINT_DB_prepare (PGconn *db_conn);
int
TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn,
uint16_t newcoin_index,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
const struct GNUNET_CRYPTO_rsa_Signature *ev_sig);
struct GNUNET_CRYPTO_rsa_Signature *
TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn,
uint16_t newcoin_index,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);
int
TALER_MINT_DB_set_reveal_ok (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);

View File

@ -22,16 +22,6 @@
* - actually abstract DB implementation (i.e. via plugin logic)
* (this file should remain largely unchanged with the exception
* of the PQ-specific DB handle types)
* - /refresh/melt:
* + properly check all conditions and handle errors
* + properly check transaction logic
* + check for leaks
* + check low-level API
* - /refresh/reveal:
* + properly check all conditions and handle errors
* + properly check transaction logic
* + check for leaks
* + check low-level API
* - /refresh/link:
* + check low-level API
* + separate DB logic from response generation
@ -760,47 +750,6 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,
}
/**
* Send response for "/refresh/reveal".
*
* @param connection the MHD connection
* @param db_conn the connection to the mint's db
* @param refresh_session_pub the refresh session's public key
* @return a MHD result code
*/
static int
helper_refresh_reveal_send_response (struct MHD_Connection *connection,
PGconn *db_conn,
const struct RefreshSession *refresh_session,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub)
{
int res;
unsigned int newcoin_index;
struct GNUNET_CRYPTO_rsa_Signature **sigs;
sigs = GNUNET_malloc (refresh_session->num_newcoins *
sizeof (struct GNUNET_CRYPTO_rsa_Signature *));
for (newcoin_index = 0; newcoin_index < refresh_session->num_newcoins; newcoin_index++)
{
sigs[newcoin_index] = TALER_MINT_DB_get_refresh_collectable (db_conn,
newcoin_index,
refresh_session_pub);
if (NULL == sigs[newcoin_index])
{
// FIXME: return 'internal error'
GNUNET_break (0);
GNUNET_free (sigs);
return MHD_NO;
}
}
res = TALER_MINT_reply_refresh_reveal_success (connection,
refresh_session->num_newcoins,
sigs);
GNUNET_free (sigs);
return res;
}
/**
* Check if the given @a transfer_privs correspond to an honest
* commitment for the given session.
@ -812,9 +761,10 @@ helper_refresh_reveal_send_response (struct MHD_Connection *connection,
* @param refresh_session session to query
* @param off commitment offset to check
* @param num_oldcoins size of the @a transfer_privs and @a melts arrays
* @param num_newcoins number of newcoins being generated
* @param transfer_privs private transfer keys
* @param melts array of melted coins
* @param num_newcoins number of newcoins being generated
* @param denom_pub array of @a num_newcoins keys for the new coins
* @return #GNUNET_OK if the committment was honest,
* #GNUNET_NO if there was a problem and we generated an error message
* #GNUNET_SYSERR if we could not even generate an error message
@ -825,9 +775,10 @@ check_commitment (struct MHD_Connection *connection,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session,
unsigned int off,
unsigned int num_oldcoins,
unsigned int num_newcoins,
const struct GNUNET_CRYPTO_EcdsaPrivateKey *transfer_privs,
const struct RefreshMelt *melts)
const struct RefreshMelt *melts,
unsigned int num_newcoins,
struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs)
{
unsigned int j;
int res;
@ -916,9 +867,7 @@ check_commitment (struct MHD_Connection *connection,
{
struct RefreshCommitCoin commit_coin;
struct TALER_RefreshLinkDecrypted *link_data;
// struct BlindedSignaturePurpose *coin_ev_check;
struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub;
struct GNUNET_HashCode h_msg;
char *buf;
size_t buf_len;
@ -947,17 +896,6 @@ check_commitment (struct MHD_Connection *connection,
GNUNET_CRYPTO_ecdsa_key_get_public (&link_data->coin_priv,
&coin_pub);
/* FIXME: like the melts,
do get these ONCE outside of the kappa-loop! */
denom_pub = TALER_MINT_DB_get_refresh_order (db_conn,
refresh_session,
j);
if (NULL == denom_pub)
{
GNUNET_break (0);
return (MHD_YES == TALER_MINT_reply_internal_db_error (connection))
? GNUNET_NO : GNUNET_SYSERR;
}
/* FIXME: we had envisioned a more complex scheme to derive
the message to sign for a blinded coin...
FIXME: we should have a function in util/ to do this! */
@ -967,7 +905,7 @@ check_commitment (struct MHD_Connection *connection,
if (0 == (buf_len =
GNUNET_CRYPTO_rsa_blind (&h_msg,
link_data->blinding_key,
denom_pub,
denom_pubs[j],
&buf)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@ -998,6 +936,62 @@ check_commitment (struct MHD_Connection *connection,
}
/**
* Mint a coin as part of a refresh operation. Obtains the
* envelope from the database and performs the signing operation.
*
* @param connection the MHD connection to handle
* @param db_conn database connection to use
* @param refresh_session session to query
* @param key_state key state to lookup denomination pubs
* @param denom_pub denomination key for the coin to create
* @param noreveal_index which index should we use to obtain the
* envelope for the coin, based on cut-and-choose
* @param coin_off number of the coin
* @return NULL on error, otherwise signature over the coin
*/
static struct GNUNET_CRYPTO_rsa_Signature *
refresh_mint_coin (struct MHD_Connection *connection,
PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session,
struct MintKeyState *key_state,
const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub,
unsigned int noreveal_index,
unsigned int coin_off)
{
struct RefreshCommitCoin commit_coin;
struct TALER_MINT_DenomKeyIssuePriv *dki;
struct GNUNET_CRYPTO_rsa_Signature *ev_sig;
int res;
res = TALER_MINT_DB_get_refresh_commit_coin (db_conn,
refresh_session,
noreveal_index,
coin_off,
&commit_coin);
if (GNUNET_OK != res)
{
GNUNET_break (0);
return NULL;
}
dki = TALER_MINT_get_denom_key (key_state, denom_pub);
if (NULL == dki)
{
GNUNET_break (0);
return NULL;
}
ev_sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv,
commit_coin.coin_ev,
commit_coin.coin_ev_size);
if (NULL == ev_sig)
{
GNUNET_break (0);
return NULL;
}
return ev_sig;
}
/**
* Execute a "/refresh/reveal". The client is revealing to us the
* transfer keys for @a kappa-1 sets of coins. Verify that the
@ -1024,6 +1018,8 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
struct RefreshSession refresh_session;
struct MintKeyState *key_state;
struct RefreshMelt *melts;
struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs;
struct GNUNET_CRYPTO_rsa_Signature **ev_sigs;
unsigned int i;
unsigned int j;
unsigned int off;
@ -1059,7 +1055,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
melts = GNUNET_malloc (refresh_session.num_oldcoins *
sizeof (struct RefreshMelt));
for (j = 0; j < refresh_session.num_oldcoins; j++)
for (j=0;j<refresh_session.num_oldcoins;j++)
{
if (GNUNET_OK !=
TALER_MINT_DB_get_refresh_melt (db_conn,
@ -1072,9 +1068,28 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
return TALER_MINT_reply_internal_db_error (connection);
}
}
denom_pubs = GNUNET_malloc (refresh_session.num_newcoins *
sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *));
for (j=0;j<refresh_session.num_newcoins;j++)
{
denom_pubs[j] = TALER_MINT_DB_get_refresh_order (db_conn,
refresh_session_pub,
j);
if (NULL == denom_pubs[j])
{
GNUNET_break (0);
for (i=0;i<j;i++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[i]);
GNUNET_free (denom_pubs);
GNUNET_free (melts);
return (MHD_YES == TALER_MINT_reply_internal_db_error (connection))
? GNUNET_NO : GNUNET_SYSERR;
}
}
off = 0;
for (i = 0; i < refresh_session.kappa - 1; i++)
for (i=0;i<refresh_session.kappa - 1;i++)
{
if (i == refresh_session.noreveal_index)
off = 1;
@ -1084,100 +1099,77 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
refresh_session_pub,
i + off,
refresh_session.num_oldcoins,
refresh_session.num_newcoins,
transfer_privs[i + off],
melts)))
melts,
refresh_session.num_newcoins,
denom_pubs)))
{
for (j=0;j<refresh_session.num_newcoins;j++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]);
GNUNET_free (denom_pubs);
GNUNET_free (melts);
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
}
}
GNUNET_free (melts);
/* Client request OK, start transaction */
if (GNUNET_OK !=
TALER_MINT_DB_transaction (db_conn))
{
GNUNET_break (0);
for (j=0;j<refresh_session.num_newcoins;j++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]);
GNUNET_free (denom_pubs);
return TALER_MINT_reply_internal_db_error (connection);
}
for (j = 0; j < refresh_session.num_newcoins; j++)
ev_sigs = GNUNET_malloc (refresh_session.num_newcoins *
sizeof (struct GNUNET_CRYPTO_rsa_Signature *));
key_state = TALER_MINT_key_state_acquire ();
for (j=0;j<refresh_session.num_newcoins;j++)
{
struct RefreshCommitCoin commit_coin;
struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub;
struct TALER_MINT_DenomKeyIssuePriv *dki;
struct GNUNET_CRYPTO_rsa_Signature *ev_sig;
res = TALER_MINT_DB_get_refresh_commit_coin (db_conn,
refresh_session_pub,
refresh_session.noreveal_index % refresh_session.kappa,
j,
&commit_coin);
if (GNUNET_OK != res)
ev_sigs[j] = refresh_mint_coin (connection,
db_conn,
refresh_session_pub,
key_state,
denom_pubs[j],
refresh_session.noreveal_index,
j);
if (NULL == ev_sigs[j])
{
GNUNET_break (0);
// FIXME: return error code!
return MHD_NO;
}
denom_pub = TALER_MINT_DB_get_refresh_order (db_conn,
refresh_session_pub,
j);
if (NULL == denom_pub)
{
GNUNET_break (0);
// FIXME: return error code!
return MHD_NO;
}
key_state = TALER_MINT_key_state_acquire ();
dki = TALER_MINT_get_denom_key (key_state, denom_pub);
TALER_MINT_key_state_release (key_state);
if (NULL == dki)
{
GNUNET_break (0);
// FIXME: return error code!
return MHD_NO;
}
ev_sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv,
commit_coin.coin_ev,
commit_coin.coin_ev_size);
if (NULL == ev_sig)
{
GNUNET_break (0);
// FIXME: return error code!
return MHD_NO;
}
res = TALER_MINT_DB_insert_refresh_collectable (db_conn,
j,
refresh_session_pub,
ev_sig);
if (GNUNET_OK != res)
{
GNUNET_break (0);
// FIXME: return error code!
return MHD_NO;
TALER_MINT_key_state_release (key_state);
for (i=0;i<j;i++)
GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i]);
GNUNET_free (ev_sigs);
for (j=0;j<refresh_session.num_newcoins;j++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]);
GNUNET_free (denom_pubs);
return TALER_MINT_reply_internal_db_error (connection);
}
}
/* mark that reveal was successful */
res = TALER_MINT_DB_set_reveal_ok (db_conn, refresh_session_pub);
if (GNUNET_OK != res)
{
GNUNET_break (0);
// FIXME: return error code!
return MHD_NO;
}
TALER_MINT_key_state_release (key_state);
for (j=0;j<refresh_session.num_newcoins;j++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]);
GNUNET_free (denom_pubs);
if (GNUNET_OK !=
TALER_MINT_DB_commit (db_conn))
{
LOG_WARNING ("/refresh/reveal transaction commit failed\n");
for (i=0;i<refresh_session.num_newcoins;i++)
GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i]);
GNUNET_free (ev_sigs);
return TALER_MINT_reply_commit_error (connection);
}
return helper_refresh_reveal_send_response (connection,
db_conn,
&refresh_session,
refresh_session_pub);
res = TALER_MINT_reply_refresh_reveal_success (connection,
refresh_session.num_newcoins,
ev_sigs);
for (i=0;i<refresh_session.num_newcoins;i++)
GNUNET_CRYPTO_rsa_signature_free (ev_sigs[i]);
GNUNET_free (ev_sigs);
return res;
}