fix DB API for generic blinded planchet storage

This commit is contained in:
Christian Grothoff 2022-02-07 13:14:25 +01:00
parent b9ea075d61
commit b2e6fcae1a
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
8 changed files with 333 additions and 65 deletions

View File

@ -6094,8 +6094,7 @@ postgres_insert_refresh_reveal (
GNUNET_PQ_query_param_uint32 (&i), GNUNET_PQ_query_param_uint32 (&i),
GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig), GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub), GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
GNUNET_PQ_query_param_fixed_size (rrc->coin_ev, TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
rrc->coin_ev_size),
GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash), GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig), TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
@ -6202,15 +6201,14 @@ add_revealed_coins (void *cls,
&rrc->orig_coin_link_sig), &rrc->orig_coin_link_sig),
GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev", GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
&rrc->coin_envelope_hash), &rrc->coin_envelope_hash),
GNUNET_PQ_result_spec_variable_size ("coin_ev", TALER_PQ_result_spec_blinded_planchet ("coin_ev",
(void **) &rrc->coin_ev, &rrc->blinded_planchet),
&rrc->coin_ev_size),
TALER_PQ_result_spec_blinded_denom_sig ("ev_sig", TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
&rrc->coin_sig), &rrc->coin_sig),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };
if (NULL != rrc->coin_ev) if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
{ {
/* duplicate offset, not allowed */ /* duplicate offset, not allowed */
GNUNET_break (0); GNUNET_break (0);
@ -6293,10 +6291,9 @@ cleanup:
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i]; struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
TALER_blinded_denom_sig_free (&rrc->coin_sig); TALER_blinded_denom_sig_free (&rrc->coin_sig);
GNUNET_free (rrc->coin_ev); TALER_blinded_planchet_free (&rrc->blinded_planchet);
} }
GNUNET_free (grctx.rrcs); GNUNET_free (grctx.rrcs);
return qs; return qs;
} }

View File

@ -433,10 +433,9 @@ check_refresh_reveal_cb (
&revealed_coins[cnt]; &revealed_coins[cnt];
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt]; const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt];
GNUNET_assert (acoin->coin_ev_size == bcoin->coin_ev_size);
GNUNET_assert (0 == GNUNET_assert (0 ==
GNUNET_memcmp (acoin->coin_ev, TALER_blinded_planchet_cmp (&acoin->blinded_planchet,
bcoin->coin_ev)); &bcoin->blinded_planchet));
GNUNET_assert (0 == GNUNET_assert (0 ==
GNUNET_memcmp (&acoin->h_denom_pub, GNUNET_memcmp (&acoin->h_denom_pub,
&bcoin->h_denom_pub)); &bcoin->h_denom_pub));
@ -1735,8 +1734,8 @@ run (void *cls)
{ {
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
struct GNUNET_TIME_Timestamp now; struct GNUNET_TIME_Timestamp now;
struct TALER_BlindedPlanchet blinded_planchet; struct TALER_BlindedRsaPlanchet *rp;
struct TALER_BlindedPlanchet *bp;
now = GNUNET_TIME_timestamp_get (); now = GNUNET_TIME_timestamp_get ();
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
@ -1749,31 +1748,25 @@ run (void *cls)
GNUNET_assert (NULL != new_dkp[cnt]); GNUNET_assert (NULL != new_dkp[cnt]);
new_denom_pubs[cnt] = new_dkp[cnt]->pub; new_denom_pubs[cnt] = new_dkp[cnt]->pub;
ccoin = &revealed_coins[cnt]; ccoin = &revealed_coins[cnt];
ccoin->coin_ev_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( bp = &ccoin->blinded_planchet;
bp->cipher = TALER_DENOMINATION_RSA;
rp = &bp->details.rsa_blinded_planchet;
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_QUALITY_WEAK,
(RSA_KEY_SIZE / 8) - 1); (RSA_KEY_SIZE / 8) - 1);
ccoin->coin_ev = GNUNET_malloc (ccoin->coin_ev_size); rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
ccoin->coin_ev, rp->blinded_msg,
ccoin->coin_ev_size); rp->blinded_msg_size);
blinded_planchet.cipher = TALER_DENOMINATION_RSA;
blinded_planchet.details.rsa_blinded_planchet.blinded_msg =
ccoin->coin_ev;
blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size =
ccoin->coin_ev_size;
TALER_denom_pub_hash (&new_dkp[cnt]->pub, TALER_denom_pub_hash (&new_dkp[cnt]->pub,
&ccoin->h_denom_pub); &ccoin->h_denom_pub);
TALER_coin_ev_hash (&blinded_planchet, TALER_coin_ev_hash (bp,
&ccoin->h_denom_pub, &ccoin->h_denom_pub,
&ccoin->coin_envelope_hash); &ccoin->coin_envelope_hash);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_denom_sign_blinded (&ccoin->coin_sig, TALER_denom_sign_blinded (&ccoin->coin_sig,
&new_dkp[cnt]->priv, &new_dkp[cnt]->priv,
&blinded_planchet)); bp));
} }
RND_BLK (&tprivs); RND_BLK (&tprivs);
RND_BLK (&tpub); RND_BLK (&tpub);
@ -1793,11 +1786,13 @@ run (void *cls)
{ {
struct TALER_BlindedCoinHash h_coin_ev; struct TALER_BlindedCoinHash h_coin_ev;
struct TALER_CoinSpendPublicKeyP ocp; struct TALER_CoinSpendPublicKeyP ocp;
struct TALER_DenominationHash denom_hash;
GNUNET_CRYPTO_hash (revealed_coins[0].coin_ev, TALER_denom_pub_hash (&new_denom_pubs[0],
revealed_coins[0].coin_ev_size, &denom_hash);
&h_coin_ev.hash); TALER_coin_ev_hash (&revealed_coins[0].blinded_planchet,
&denom_hash,
&h_coin_ev);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_old_coin_by_h_blind (plugin->cls, plugin->get_old_coin_by_h_blind (plugin->cls,
&h_coin_ev, &h_coin_ev,
@ -2406,7 +2401,7 @@ drop:
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
{ {
TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig); TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
GNUNET_free (revealed_coins[cnt].coin_ev); TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
} }
GNUNET_free (revealed_coins); GNUNET_free (revealed_coins);
revealed_coins = NULL; revealed_coins = NULL;

View File

@ -461,7 +461,6 @@ struct TALER_RsaPubHashP
struct GNUNET_HashCode hash; struct GNUNET_HashCode hash;
}; };
GNUNET_NETWORK_STRUCT_BEGIN
/** /**
* Master key material for the deriviation of * Master key material for the deriviation of
@ -478,29 +477,6 @@ struct TALER_PlanchetSecretsP
}; };
GNUNET_NETWORK_STRUCT_END
/**
* Hash @a rsa.
*
* @param rsa key to hash
* @param[out] h_rsa where to write the result
*/
void
TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
struct TALER_RsaPubHashP *h_rsa);
/**
* Hash @a cs.
*
* @param cs key to hash
* @param[out] h_cs where to write the result
*/
void
TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
struct TALER_CsPubHashP *h_cs);
/** /**
* Hash used to represent a denomination public key * Hash used to represent a denomination public key
* and associated age restrictions (if any). * and associated age restrictions (if any).
@ -632,6 +608,27 @@ struct TALER_ExtensionConfigHash
GNUNET_NETWORK_STRUCT_END GNUNET_NETWORK_STRUCT_END
/**
* Hash @a rsa.
*
* @param rsa key to hash
* @param[out] h_rsa where to write the result
*/
void
TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
struct TALER_RsaPubHashP *h_rsa);
/**
* Hash @a cs.
*
* @param cs key to hash
* @param[out] h_cs where to write the result
*/
void
TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
struct TALER_CsPubHashP *h_cs);
/** /**
* Types of public keys used for denominations in Taler. * Types of public keys used for denominations in Taler.
*/ */
@ -1258,6 +1255,19 @@ TALER_blinded_denom_sig_cmp (
const struct TALER_BlindedDenominationSignature *sig2); const struct TALER_BlindedDenominationSignature *sig2);
/**
* Compare two blinded planchets.
*
* @param sig1 first blinded planchet
* @param sig2 second blinded planchet
* @return 0 if the keys are equal, otherwise -1 or 1
*/
int
TALER_blinded_planchet_cmp (
const struct TALER_BlindedPlanchet *bp1,
const struct TALER_BlindedPlanchet *bp2);
/** /**
* Obtain denomination public key from a denomination private key. * Obtain denomination public key from a denomination private key.
* *

View File

@ -1646,14 +1646,9 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
struct TALER_BlindedDenominationSignature coin_sig; struct TALER_BlindedDenominationSignature coin_sig;
/** /**
* Blinded message to be signed (in envelope), with @e coin_env_size bytes. * Blinded message to be signed (in envelope).
*/ */
void *coin_ev; struct TALER_BlindedPlanchet blinded_planchet;
/**
* Number of bytes in @e coin_ev.
*/
size_t coin_ev_size;
}; };

View File

@ -77,6 +77,19 @@ TALER_PQ_query_param_denom_sig (
const struct TALER_DenominationSignature *denom_sig); const struct TALER_DenominationSignature *denom_sig);
/**
* Generate query parameter for a blinded planchet.
* Internally, various attributes of the blinded
* planchet will be serialized into on
* variable-size BLOB.
*
* @param x pointer to the query parameter to pass
*/
struct GNUNET_PQ_QueryParam
TALER_PQ_query_param_blinded_planchet (
const struct TALER_BlindedPlanchet *bp);
/** /**
* Generate query parameter for a blinded denomination signature. Internally, * Generate query parameter for a blinded denomination signature. Internally,
* the various attributes of the signature will be serialized into on * the various attributes of the signature will be serialized into on
@ -166,6 +179,19 @@ TALER_PQ_result_spec_blinded_denom_sig (
struct TALER_BlindedDenominationSignature *denom_sig); struct TALER_BlindedDenominationSignature *denom_sig);
/**
* Blinded planchet expected.
*
* @param name name of the field in the table
* @param[out] bp where to store the blinded planchet
* @return array entry for the result specification to use
*/
struct GNUNET_PQ_ResultSpec
TALER_PQ_result_spec_blinded_planchet (
const char *name,
struct TALER_BlindedPlanchet *bp);
/** /**
* json_t expected. * json_t expected.
* *

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015, 2016, 2021 Taler Systems SA Copyright (C) 2014, 2015, 2016, 2021, 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the 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 terms of the GNU General Public License as published by the Free Software
@ -436,6 +436,97 @@ TALER_PQ_query_param_blinded_denom_sig (
} }
/**
* Function called to convert input argument into SQL parameters.
*
* @param cls closure
* @param data pointer to input argument
* @param data_len number of bytes in @a data (if applicable)
* @param[out] param_values SQL data to set
* @param[out] param_lengths SQL length data to set
* @param[out] param_formats SQL format data to set
* @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
* @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
* @param scratch_length number of entries left in @a scratch
* @return -1 on error, number of offsets used in @a scratch otherwise
*/
static int
qconv_blinded_planchet (void *cls,
const void *data,
size_t data_len,
void *param_values[],
int param_lengths[],
int param_formats[],
unsigned int param_length,
void *scratch[],
unsigned int scratch_length)
{
const struct TALER_BlindedPlanchet *bp = data;
size_t tlen;
size_t len;
uint32_t be[2];
char *buf;
(void) cls;
(void) data_len;
GNUNET_assert (1 == param_length);
GNUNET_assert (scratch_length > 0);
GNUNET_break (NULL == cls);
be[0] = htonl ((uint32_t) bp->cipher);
be[1] = htonl (0x0100); /* magic marker: blinded */
switch (bp->cipher)
{
case TALER_DENOMINATION_RSA:
tlen = bp->details.rsa_blinded_planchet.blinded_msg_size;
break;
case TALER_DENOMINATION_CS:
tlen = sizeof (bp->details.cs_blinded_planchet);
break;
default:
GNUNET_assert (0);
}
len = tlen + sizeof (be);
buf = GNUNET_malloc (len);
memcpy (buf,
&be,
sizeof (be));
switch (bp->cipher)
{
case TALER_DENOMINATION_RSA:
memcpy (&buf[sizeof (be)],
bp->details.rsa_blinded_planchet.blinded_msg,
tlen);
break;
case TALER_DENOMINATION_CS:
memcpy (&buf[sizeof (be)],
&bp->details.cs_blinded_planchet,
tlen);
break;
default:
GNUNET_assert (0);
}
scratch[0] = buf;
param_values[0] = (void *) buf;
param_lengths[0] = len;
param_formats[0] = 1;
return 1;
}
struct GNUNET_PQ_QueryParam
TALER_PQ_query_param_blinded_planchet (
const struct TALER_BlindedPlanchet *bp)
{
struct GNUNET_PQ_QueryParam res = {
.conv = &qconv_blinded_planchet,
.data = bp,
.num_params = 1
};
return res;
}
/** /**
* Function called to convert input argument into SQL parameters. * Function called to convert input argument into SQL parameters.
* *

View File

@ -730,4 +730,129 @@ TALER_PQ_result_spec_blinded_denom_sig (
} }
/**
* Extract data from a Postgres database @a result at row @a row.
*
* @param cls closure
* @param result where to extract data from
* @param int row to extract data from
* @param fname name (or prefix) of the fields to extract from
* @param[in,out] dst_size where to store size of result, may be NULL
* @param[out] dst where to store the result
* @return
* #GNUNET_YES if all results could be extracted
* #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
*/
static enum GNUNET_GenericReturnValue
extract_blinded_planchet (void *cls,
PGresult *result,
int row,
const char *fname,
size_t *dst_size,
void *dst)
{
struct TALER_BlindedPlanchet *bp = dst;
size_t len;
const char *res;
int fnum;
uint32_t be[2];
(void) cls;
(void) dst_size;
fnum = PQfnumber (result,
fname);
if (fnum < 0)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
if (PQgetisnull (result,
row,
fnum))
return GNUNET_NO;
/* if a field is null, continue but
* remember that we now return a different result */
len = PQgetlength (result,
row,
fnum);
res = PQgetvalue (result,
row,
fnum);
if (len < sizeof (be))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
memcpy (&be,
res,
sizeof (be));
if (0x0100 != ntohl (be[1])) /* magic marker: blinded */
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
res += sizeof (be);
len -= sizeof (be);
bp->cipher = ntohl (be[0]);
switch (bp->cipher)
{
case TALER_DENOMINATION_RSA:
bp->details.rsa_blinded_planchet.blinded_msg_size
= len;
bp->details.rsa_blinded_planchet.blinded_msg
= GNUNET_memdup (res,
len);
return GNUNET_OK;
case TALER_DENOMINATION_CS:
if (sizeof (bp->details.cs_blinded_planchet) != len)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
memcpy (&bp->details.cs_blinded_planchet,
res,
len);
return GNUNET_OK;
default:
GNUNET_break (0);
}
return GNUNET_SYSERR;
}
/**
* Function called to clean up memory allocated
* by a #GNUNET_PQ_ResultConverter.
*
* @param cls closure
* @param rd result data to clean up
*/
static void
clean_blinded_planchet (void *cls,
void *rd)
{
struct TALER_BlindedPlanchet *bp = rd;
(void) cls;
TALER_blinded_planchet_free (bp);
}
struct GNUNET_PQ_ResultSpec
TALER_PQ_result_spec_blinded_planchet (
const char *name,
struct TALER_BlindedPlanchet *bp)
{
struct GNUNET_PQ_ResultSpec res = {
.conv = &extract_blinded_planchet,
.cleaner = &clean_blinded_planchet,
.dst = (void *) bp,
.fname = name
};
return res;
}
/* end of pq_result_helper.c */ /* end of pq_result_helper.c */

View File

@ -638,6 +638,35 @@ TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1,
} }
int
TALER_blinded_planchet_cmp (
const struct TALER_BlindedPlanchet *bp1,
const struct TALER_BlindedPlanchet *bp2)
{
if (bp1->cipher != bp2->cipher)
return (bp1->cipher > bp2->cipher) ? 1 : -1;
switch (bp1->cipher)
{
case TALER_DENOMINATION_INVALID:
return 0;
case TALER_DENOMINATION_RSA:
if (bp1->details.rsa_blinded_planchet.blinded_msg_size !=
bp2->details.rsa_blinded_planchet.blinded_msg_size)
return (bp1->details.rsa_blinded_planchet.blinded_msg_size >
bp2->details.rsa_blinded_planchet.blinded_msg_size) ? 1 : -1;
return memcmp (bp1->details.rsa_blinded_planchet.blinded_msg,
bp2->details.rsa_blinded_planchet.blinded_msg,
bp1->details.rsa_blinded_planchet.blinded_msg_size);
case TALER_DENOMINATION_CS:
return GNUNET_memcmp (&bp1->details.cs_blinded_planchet,
&bp2->details.cs_blinded_planchet);
default:
GNUNET_assert (0);
}
return -2;
}
int int
TALER_blinded_denom_sig_cmp ( TALER_blinded_denom_sig_cmp (
const struct TALER_BlindedDenominationSignature *sig1, const struct TALER_BlindedDenominationSignature *sig1,