diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-02-07 13:14:25 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-02-07 13:14:25 +0100 |
commit | b2e6fcae1a9b96f086c61f13f4c2c98338c4e414 (patch) | |
tree | 6c5c8c264ca674dd8c0e303daf3207bbaff65315 | |
parent | b9ea075d61dcd47951b2f7f962025476c045aa57 (diff) |
fix DB API for generic blinded planchet storage
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 13 | ||||
-rw-r--r-- | src/exchangedb/test_exchangedb.c | 45 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 58 | ||||
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 9 | ||||
-rw-r--r-- | src/include/taler_pq_lib.h | 26 | ||||
-rw-r--r-- | src/pq/pq_query_helper.c | 93 | ||||
-rw-r--r-- | src/pq/pq_result_helper.c | 125 | ||||
-rw-r--r-- | src/util/denom.c | 29 |
8 files changed, 333 insertions, 65 deletions
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 713e11e81..9694b73ce 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -6094,8 +6094,7 @@ postgres_insert_refresh_reveal ( 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->h_denom_pub), - GNUNET_PQ_query_param_fixed_size (rrc->coin_ev, - rrc->coin_ev_size), + TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet), GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash), TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig), GNUNET_PQ_query_param_end @@ -6202,15 +6201,14 @@ add_revealed_coins (void *cls, &rrc->orig_coin_link_sig), GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev", &rrc->coin_envelope_hash), - GNUNET_PQ_result_spec_variable_size ("coin_ev", - (void **) &rrc->coin_ev, - &rrc->coin_ev_size), + TALER_PQ_result_spec_blinded_planchet ("coin_ev", + &rrc->blinded_planchet), TALER_PQ_result_spec_blinded_denom_sig ("ev_sig", &rrc->coin_sig), GNUNET_PQ_result_spec_end }; - if (NULL != rrc->coin_ev) + if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher) { /* duplicate offset, not allowed */ GNUNET_break (0); @@ -6293,10 +6291,9 @@ cleanup: struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i]; TALER_blinded_denom_sig_free (&rrc->coin_sig); - GNUNET_free (rrc->coin_ev); + TALER_blinded_planchet_free (&rrc->blinded_planchet); } GNUNET_free (grctx.rrcs); - return qs; } diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index 952d329fe..f86f5451c 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -433,10 +433,9 @@ check_refresh_reveal_cb ( &revealed_coins[cnt]; const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt]; - GNUNET_assert (acoin->coin_ev_size == bcoin->coin_ev_size); GNUNET_assert (0 == - GNUNET_memcmp (acoin->coin_ev, - bcoin->coin_ev)); + TALER_blinded_planchet_cmp (&acoin->blinded_planchet, + &bcoin->blinded_planchet)); GNUNET_assert (0 == GNUNET_memcmp (&acoin->h_denom_pub, &bcoin->h_denom_pub)); @@ -1735,8 +1734,8 @@ run (void *cls) { struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; struct GNUNET_TIME_Timestamp now; - struct TALER_BlindedPlanchet blinded_planchet; - + struct TALER_BlindedRsaPlanchet *rp; + struct TALER_BlindedPlanchet *bp; now = GNUNET_TIME_timestamp_get (); new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, @@ -1749,31 +1748,25 @@ run (void *cls) GNUNET_assert (NULL != new_dkp[cnt]); new_denom_pubs[cnt] = new_dkp[cnt]->pub; 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, (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, - ccoin->coin_ev, - ccoin->coin_ev_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; - + rp->blinded_msg, + rp->blinded_msg_size); TALER_denom_pub_hash (&new_dkp[cnt]->pub, &ccoin->h_denom_pub); - TALER_coin_ev_hash (&blinded_planchet, + TALER_coin_ev_hash (bp, &ccoin->h_denom_pub, &ccoin->coin_envelope_hash); - - GNUNET_assert (GNUNET_OK == TALER_denom_sign_blinded (&ccoin->coin_sig, &new_dkp[cnt]->priv, - &blinded_planchet)); + bp)); } RND_BLK (&tprivs); RND_BLK (&tpub); @@ -1793,11 +1786,13 @@ run (void *cls) { struct TALER_BlindedCoinHash h_coin_ev; struct TALER_CoinSpendPublicKeyP ocp; + struct TALER_DenominationHash denom_hash; - GNUNET_CRYPTO_hash (revealed_coins[0].coin_ev, - revealed_coins[0].coin_ev_size, - &h_coin_ev.hash); - + TALER_denom_pub_hash (&new_denom_pubs[0], + &denom_hash); + TALER_coin_ev_hash (&revealed_coins[0].blinded_planchet, + &denom_hash, + &h_coin_ev); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_old_coin_by_h_blind (plugin->cls, &h_coin_ev, @@ -2406,7 +2401,7 @@ drop: for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) { 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); revealed_coins = NULL; diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index b3e4ba264..189d4b063 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -461,7 +461,6 @@ struct TALER_RsaPubHashP struct GNUNET_HashCode hash; }; -GNUNET_NETWORK_STRUCT_BEGIN /** * 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 * and associated age restrictions (if any). @@ -633,6 +609,27 @@ 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. */ enum TALER_DenominationCipher @@ -1259,6 +1256,19 @@ TALER_blinded_denom_sig_cmp ( /** + * 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. * * @param denom_priv private key to convert diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 633cf2064..8269672fe 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1646,14 +1646,9 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin 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; - - /** - * Number of bytes in @e coin_ev. - */ - size_t coin_ev_size; + struct TALER_BlindedPlanchet blinded_planchet; }; diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 2189a4f61..fa3128462 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -78,6 +78,19 @@ TALER_PQ_query_param_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, * the various attributes of the signature will be serialized into on * variable-size BLOB. @@ -167,6 +180,19 @@ TALER_PQ_result_spec_blinded_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. * * @param name name of the field in the table diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c index ca1e94efb..8d6df60ce 100644 --- a/src/pq/pq_query_helper.c +++ b/src/pq/pq_query_helper.c @@ -1,6 +1,6 @@ /* 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 terms of the GNU General Public License as published by the Free Software @@ -440,6 +440,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. + * + * @param cls closure * @param data pointer to input argument, here a `json_t *` * @param data_len number of bytes in @a data (if applicable) * @param[out] param_values SQL data to set diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c index 02733f298..6ee5da53e 100644 --- a/src/pq/pq_result_helper.c +++ b/src/pq/pq_result_helper.c @@ -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 */ diff --git a/src/util/denom.c b/src/util/denom.c index 00d7ec791..caaa4f4e8 100644 --- a/src/util/denom.c +++ b/src/util/denom.c @@ -639,6 +639,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 TALER_blinded_denom_sig_cmp ( const struct TALER_BlindedDenominationSignature *sig1, const struct TALER_BlindedDenominationSignature *sig2) |