fix major bug with SQL statement missing ORDER BY freshcoin_index resulting in possible link failures (but usually lucky with old DB schema)

This commit is contained in:
Christian Grothoff 2021-01-10 00:54:12 +01:00
parent 02ecf68a3d
commit ca66a1d1af
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
10 changed files with 174 additions and 74 deletions

View File

@ -83,8 +83,8 @@ handle_link_data (void *cls,
obj = json_pack ("{s:o, s:o, s:o}",
"denom_pub",
GNUNET_JSON_from_rsa_public_key
(pos->denom_pub.rsa_public_key),
GNUNET_JSON_from_rsa_public_key (
pos->denom_pub.rsa_public_key),
"ev_sig",
GNUNET_JSON_from_rsa_signature
(pos->ev_sig.rsa_signature),

View File

@ -349,7 +349,7 @@ refreshes_reveal_transaction (void *cls,
else
{
/* Reconstruct coin envelopes from transfer private key */
struct TALER_TransferPrivateKeyP *tpriv
const struct TALER_TransferPrivateKeyP *tpriv
= &rctx->transfer_privs[i - off];
struct TALER_TransferSecretP ts;
@ -695,32 +695,22 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
if (GNUNET_OK != res)
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
/* Check link_sigs[i] signature */
if (GNUNET_OK !=
TALER_wallet_link_verify (
&dk_h[i],
&rctx->gamma_tp,
rcds[i].coin_ev,
rcds[i].coin_ev_size,
&melt.session.coin.coin_pub,
&link_sigs[i]))
{
struct TALER_LinkDataPS ldp = {
.purpose.size = htonl (sizeof (ldp)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
.h_denom_pub = dk_h[i],
.old_coin_pub = melt.session.coin.coin_pub,
.transfer_pub = rctx->gamma_tp
};
GNUNET_CRYPTO_hash (rcds[i].coin_ev,
rcds[i].coin_ev_size,
&ldp.coin_envelope_hash);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_WALLET_COIN_LINK,
&ldp,
&link_sigs[i].eddsa_signature,
&melt.session.coin.coin_pub.eddsa_pub))
{
GNUNET_break_op (0);
ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_LINK_SIGNATURE_INVALID,
NULL);
goto cleanup;
}
GNUNET_break_op (0);
ret = TALER_MHD_reply_with_error (
connection,
MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_LINK_SIGNATURE_INVALID,
NULL);
goto cleanup;
}
}

View File

@ -280,7 +280,6 @@ COMMENT ON COLUMN refunds.deposit_serial_id
IS 'Identifies ONLY the merchant_pub, h_contract_terms and known_coin_id. Multiple deposits may match a refund, this only identifies one of them.';
-- Create additional tables...
CREATE TABLE IF NOT EXISTS auditors

View File

@ -794,7 +794,7 @@ postgres_get_session (void *cls)
",h_coin_ev"
",ev_sig"
") SELECT rcx.melt_serial_id, $2, $3, "
" denominations_serial, $5, $6, $7 "
" denominations_serial, $5, $6, $7"
" FROM denominations"
" CROSS JOIN rcx"
" WHERE denom_pub_hash=$4;",
@ -1108,7 +1108,7 @@ postgres_get_session (void *cls)
" (SELECT known_coin_id "
" FROM known_coins"
" WHERE coin_pub=$1)"
" ORDER BY tp.transfer_pub",
" ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC",
1),
/* Used in #postgres_lookup_wire_transfer */
GNUNET_PQ_make_prepare ("lookup_transactions",
@ -2323,6 +2323,11 @@ postgres_preflight (void *cls,
};
(void) cls;
if (NULL == session)
{
GNUNET_break (0);
return;
}
if (NULL == session->transaction_name)
return; /* all good */
if (GNUNET_OK ==

View File

@ -1050,6 +1050,47 @@ TALER_CRYPTO_helper_esign_disconnect (
struct TALER_CRYPTO_ExchangeSignHelper *esh);
/* ********************* wallet signing ************************** */
/**
* Sign link data.
*
* @param h_denom_pub hash of the denomiantion public key of the new coin
* @param transfer_pub transfer public key
* @param coin_ev coin envelope
* @param coin_ev_size number of bytes in @a coin_ev
* @param old_coin_priv private key to sign with
* @param[out] coin_sig resulting signature
*/
void
TALER_wallet_link_sign (const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_TransferPublicKeyP *transfer_pub,
const void *coin_ev,
size_t coin_ev_size,
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
struct TALER_CoinSpendSignatureP *coin_sig);
/**
* Verify link signature.
*
* @param h_denom_pub hash of the denomiantion public key of the new coin
* @param transfer_pub transfer public key
* @param coin_ev coin envelope
* @param coin_ev_size number of bytes in @a coin_ev
* @param old_coin_priv private key to sign with
* @param coin_sig resulting signature
* @return #GNUNET_OK if the signature is valid
*/
enum GNUNET_GenericReturnValue
TALER_wallet_link_verify (
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_TransferPublicKeyP *transfer_pub,
const void *coin_ev,
size_t coin_ev_size,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig);
/* ********************* offline signing ************************** */

View File

@ -1274,6 +1274,7 @@ struct TALER_EXCHANGEDB_LinkList
* link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK
*/
struct TALER_CoinSpendSignatureP orig_coin_link_sig;
};

View File

@ -75,7 +75,7 @@ struct TALER_EXCHANGE_LinkHandle
*
* @param lh link handle
* @param json json reply with the data for one coin
* @param coin_num number of the coin to decode
* @param coin_num number of the coin
* @param trans_pub our transfer public key
* @param[out] coin_priv where to return private coin key
* @param[out] sig where to return private coin signature
@ -85,7 +85,7 @@ struct TALER_EXCHANGE_LinkHandle
static int
parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
const json_t *json,
unsigned int coin_num,
uint32_t coin_num,
const struct TALER_TransferPublicKeyP *trans_pub,
struct TALER_CoinSpendPrivateKeyP *coin_priv,
struct TALER_DenominationSignature *sig,
@ -112,7 +112,6 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
TALER_link_recover_transfer_secret (trans_pub,
&lh->coin_priv,
&secret);
@ -130,14 +129,10 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
{
struct TALER_PlanchetDetail pd;
struct GNUNET_HashCode c_hash;
struct TALER_LinkDataPS ldp = {
.purpose.size = htonl (sizeof (ldp)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
.transfer_pub = *trans_pub
};
struct TALER_CoinSpendPublicKeyP old_coin_pub;
GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv,
&ldp.old_coin_pub.eddsa_pub);
&old_coin_pub.eddsa_pub);
pub->rsa_public_key = rpub;
if (GNUNET_OK !=
TALER_planchet_prepare (pub,
@ -149,22 +144,20 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
ldp.h_denom_pub = pd.denom_pub_hash;
GNUNET_CRYPTO_hash (pd.coin_ev,
pd.coin_ev_size,
&ldp.coin_envelope_hash);
GNUNET_free (pd.coin_ev);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
&ldp,
&link_sig.eddsa_signature,
&ldp.old_coin_pub.eddsa_pub))
TALER_wallet_link_verify (&pd.denom_pub_hash,
trans_pub,
pd.coin_ev,
pd.coin_ev_size,
&old_coin_pub,
&link_sig))
{
GNUNET_break_op (0);
GNUNET_free (pd.coin_ev);
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
GNUNET_free (pd.coin_ev);
}
/* clean up */
@ -457,11 +450,11 @@ TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (&coin_pub,
sizeof (struct
TALER_CoinSpendPublicKeyP),
pub_str,
sizeof (pub_str));
end = GNUNET_STRINGS_data_to_string (
&coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP),
pub_str,
sizeof (pub_str));
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),

View File

@ -391,30 +391,20 @@ TALER_EXCHANGE_refreshes_reveal (
json_array_append_new (coin_evs,
GNUNET_JSON_from_data (pd.coin_ev,
pd.coin_ev_size)));
/* compute link signature */
{
struct TALER_CoinSpendSignatureP link_sig;
struct TALER_LinkDataPS ldp;
ldp.purpose.size = htonl (sizeof (ldp));
ldp.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK);
ldp.h_denom_pub = denom_hash;
GNUNET_CRYPTO_eddsa_key_get_public (&md->melted_coin.coin_priv.eddsa_priv,
&ldp.old_coin_pub.eddsa_pub);
ldp.transfer_pub = transfer_pub;
GNUNET_CRYPTO_hash (pd.coin_ev,
pd.coin_ev_size,
&ldp.coin_envelope_hash);
GNUNET_CRYPTO_eddsa_sign (&md->melted_coin.coin_priv.eddsa_priv,
&ldp,
&link_sig.eddsa_signature);
TALER_wallet_link_sign (&denom_hash,
&transfer_pub,
pd.coin_ev,
pd.coin_ev_size,
&md->melted_coin.coin_priv,
&link_sig);
GNUNET_assert (0 ==
json_array_append_new (link_sigs,
GNUNET_JSON_from_data_auto (
&link_sig)));
json_array_append_new (
link_sigs,
GNUNET_JSON_from_data_auto (&link_sig)));
}
GNUNET_free (pd.coin_ev);
}

View File

@ -76,6 +76,7 @@ libtalerutil_la_SOURCES = \
taler_error_codes.c \
url.c \
util.c \
wallet_signatures.c \
yna.c \
os_installation.c

View File

@ -0,0 +1,80 @@
/*
This file is part of TALER
Copyright (C) 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file secmod_signatures.c
* @brief Utility functions for Taler security module signatures
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_util.h"
#include "taler_signatures.h"
void
TALER_wallet_link_sign (const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_TransferPublicKeyP *transfer_pub,
const void *coin_ev,
size_t coin_ev_size,
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
struct TALER_CoinSpendSignatureP *coin_sig)
{
struct TALER_LinkDataPS ldp = {
.purpose.size = htonl (sizeof (ldp)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
.h_denom_pub = *h_denom_pub,
.transfer_pub = *transfer_pub
};
GNUNET_CRYPTO_hash (coin_ev,
coin_ev_size,
&ldp.coin_envelope_hash);
GNUNET_CRYPTO_eddsa_key_get_public (&old_coin_priv->eddsa_priv,
&ldp.old_coin_pub.eddsa_pub);
GNUNET_CRYPTO_eddsa_sign (&old_coin_priv->eddsa_priv,
&ldp,
&coin_sig->eddsa_signature);
}
enum GNUNET_GenericReturnValue
TALER_wallet_link_verify (
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_TransferPublicKeyP *transfer_pub,
const void *coin_ev,
size_t coin_ev_size,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig)
{
struct TALER_LinkDataPS ldp = {
.purpose.size = htonl (sizeof (ldp)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
.h_denom_pub = *h_denom_pub,
.old_coin_pub = *old_coin_pub,
.transfer_pub = *transfer_pub
};
GNUNET_CRYPTO_hash (coin_ev,
coin_ev_size,
&ldp.coin_envelope_hash);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
&ldp,
&coin_sig->eddsa_signature,
&old_coin_pub->eddsa_pub);
}
/* end of wallet_signatures.c */