From 3eae999efc0cb923aebd2bf7214c5f4093217d4f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 31 Oct 2021 17:56:56 +0100 Subject: [PATCH] distinguish between blind and non-blind denomination signatures --- src/exchange/taler-exchange-httpd_keys.c | 4 +- src/exchange/taler-exchange-httpd_keys.h | 2 +- .../taler-exchange-httpd_refreshes_reveal.c | 19 +-- src/exchange/taler-exchange-httpd_withdraw.c | 14 +- src/exchangedb/plugin_exchangedb_common.c | 2 +- src/exchangedb/plugin_exchangedb_postgres.c | 18 +-- src/include/taler_crypto_lib.h | 64 ++++++++- src/include/taler_exchange_service.h | 2 +- src/include/taler_exchangedb_plugin.h | 6 +- src/include/taler_json_lib.h | 29 ++++ src/include/taler_pq_lib.h | 25 ++++ src/json/json_helper.c | 98 +++++++++++++- src/json/json_pack.c | 26 ++++ src/lib/exchange_api_refreshes_reveal.c | 12 +- src/lib/exchange_api_withdraw.c | 2 +- src/lib/exchange_api_withdraw2.c | 8 +- src/pq/pq_query_helper.c | 94 ++++++++++++- src/pq/pq_result_helper.c | 127 +++++++++++++++++- src/util/crypto.c | 16 ++- src/util/crypto_helper_denom.c | 8 +- src/util/denom.c | 48 ++++++- 21 files changed, 550 insertions(+), 74 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index e18295c65..ad06b6684 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -1918,14 +1918,14 @@ TEH_keys_denomination_by_hash2 ( } -struct TALER_DenominationSignature +struct TALER_BlindedDenominationSignature TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub, const void *msg, size_t msg_size, enum TALER_ErrorCode *ec) { struct TEH_KeyStateHandle *ksh; - struct TALER_DenominationSignature none; + struct TALER_BlindedDenominationSignature none; memset (&none, 0, diff --git a/src/exchange/taler-exchange-httpd_keys.h b/src/exchange/taler-exchange-httpd_keys.h index db967a31b..9ad0c6a3a 100644 --- a/src/exchange/taler-exchange-httpd_keys.h +++ b/src/exchange/taler-exchange-httpd_keys.h @@ -171,7 +171,7 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh, * @return signature, the value inside the structure will be NULL on failure, * see @a ec for details about the failure */ -struct TALER_DenominationSignature +struct TALER_BlindedDenominationSignature TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub, const void *msg, size_t msg_size, diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c index 925f7a094..4ec703136 100644 --- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c +++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c @@ -55,7 +55,8 @@ static MHD_RESULT reply_refreshes_reveal_success (struct MHD_Connection *connection, unsigned int num_freshcoins, - const struct TALER_DenominationSignature *sigs) + const struct + TALER_BlindedDenominationSignature *sigs) { json_t *list; @@ -68,8 +69,8 @@ reply_refreshes_reveal_success (struct MHD_Connection *connection, json_t *obj; obj = GNUNET_JSON_PACK ( - TALER_JSON_pack_denom_sig ("ev_sig", - &sigs[freshcoin_index])); + TALER_JSON_pack_blinded_denom_sig ("ev_sig", + &sigs[freshcoin_index])); GNUNET_assert (0 == json_array_append_new (list, obj)); @@ -123,7 +124,7 @@ struct RevealContext /** * Envelopes with the signatures to be returned. Initially NULL. */ - struct TALER_DenominationSignature *ev_sigs; + struct TALER_BlindedDenominationSignature *ev_sigs; /** * Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL). @@ -187,10 +188,10 @@ check_exists_cb (void *cls, if (NULL == rctx->ev_sigs) { rctx->ev_sigs = GNUNET_new_array (num_freshcoins, - struct TALER_DenominationSignature); + struct TALER_BlindedDenominationSignature); for (unsigned int i = 0; iev_sigs[i], - &rrcs[i].coin_sig); + TALER_blinded_denom_sig_deep_copy (&rctx->ev_sigs[i], + &rrcs[i].coin_sig); } } @@ -683,7 +684,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection, /* sign _early_ (optimistic!) to keep out of transaction scope! */ rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins, - struct TALER_DenominationSignature); + struct TALER_BlindedDenominationSignature); for (unsigned int i = 0; inum_fresh_coins; i++) { enum TALER_ErrorCode ec = TALER_EC_NONE; @@ -769,7 +770,7 @@ cleanup: if (NULL != rctx->ev_sigs) { for (unsigned int i = 0; iev_sigs[i]); + TALER_blinded_denom_sig_free (&rctx->ev_sigs[i]); GNUNET_free (rctx->ev_sigs); rctx->ev_sigs = NULL; /* just to be safe... */ } diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c index d9c3b9e94..ef1bb27d9 100644 --- a/src/exchange/taler-exchange-httpd_withdraw.c +++ b/src/exchange/taler-exchange-httpd_withdraw.c @@ -199,7 +199,7 @@ withdraw_transaction (void *cls, struct WithdrawContext *wc = cls; struct TALER_EXCHANGEDB_Reserve r; enum GNUNET_DB_QueryStatus qs; - struct TALER_DenominationSignature denom_sig; + struct TALER_BlindedDenominationSignature denom_sig; #if OPTIMISTIC_SIGN /* store away optimistic signature to protect @@ -231,7 +231,7 @@ withdraw_transaction (void *cls, optimization trade-off loses in this case: we unnecessarily computed a signature :-( */ #if OPTIMISTIC_SIGN - TALER_denom_sig_free (&denom_sig); + TALER_blinded_denom_sig_free (&denom_sig); #endif return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } @@ -582,7 +582,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, { /* Even if #withdraw_transaction() failed, it may have created a signature (or we might have done it optimistically above). */ - TALER_denom_sig_free (&wc.collectable.sig); + TALER_blinded_denom_sig_free (&wc.collectable.sig); GNUNET_JSON_parse_free (spec); return mhd_ret; } @@ -593,7 +593,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, if (wc.kyc_denied) { - TALER_denom_sig_free (&wc.collectable.sig); + TALER_blinded_denom_sig_free (&wc.collectable.sig); return TALER_MHD_REPLY_JSON_PACK ( rc->connection, MHD_HTTP_ACCEPTED, @@ -607,9 +607,9 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, ret = TALER_MHD_REPLY_JSON_PACK ( rc->connection, MHD_HTTP_OK, - TALER_JSON_pack_denom_sig ("ev_sig", - &wc.collectable.sig)); - TALER_denom_sig_free (&wc.collectable.sig); + TALER_JSON_pack_blinded_denom_sig ("ev_sig", + &wc.collectable.sig)); + TALER_blinded_denom_sig_free (&wc.collectable.sig); return ret; } } diff --git a/src/exchangedb/plugin_exchangedb_common.c b/src/exchangedb/plugin_exchangedb_common.c index 2d482698d..a07ae78c1 100644 --- a/src/exchangedb/plugin_exchangedb_common.c +++ b/src/exchangedb/plugin_exchangedb_common.c @@ -49,7 +49,7 @@ common_free_reserve_history (void *cls, struct TALER_EXCHANGEDB_CollectableBlindcoin *cbc; cbc = rh->details.withdraw; - TALER_denom_sig_free (&cbc->sig); + TALER_blinded_denom_sig_free (&cbc->sig); GNUNET_free (cbc); break; } diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 017145e61..85550e980 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -4404,8 +4404,8 @@ postgres_get_withdraw_info ( struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &collectable->denom_pub_hash), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &collectable->sig), + TALER_PQ_result_spec_blinded_denom_sig ("denom_sig", + &collectable->sig), GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", &collectable->reserve_sig), GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", @@ -4456,7 +4456,7 @@ postgres_insert_withdraw_info ( struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&collectable->h_coin_envelope), GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash), - TALER_PQ_query_param_denom_sig (&collectable->sig), + TALER_PQ_query_param_blinded_denom_sig (&collectable->sig), GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub), GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_sig), TALER_PQ_query_param_absolute_time (&now), @@ -4660,8 +4660,8 @@ add_withdraw_coin (void *cls, &cbc->h_coin_envelope), GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &cbc->denom_pub_hash), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &cbc->sig), + TALER_PQ_result_spec_blinded_denom_sig ("denom_sig", + &cbc->sig), GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", &cbc->reserve_sig), TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", @@ -6088,7 +6088,7 @@ postgres_insert_refresh_reveal ( GNUNET_PQ_query_param_fixed_size (rrc->coin_ev, rrc->coin_ev_size), GNUNET_PQ_query_param_auto_from_type (&h_coin_ev), - TALER_PQ_query_param_denom_sig (&rrc->coin_sig), + TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig), GNUNET_PQ_query_param_end }; enum GNUNET_DB_QueryStatus qs; @@ -6180,8 +6180,8 @@ add_revealed_coins (void *cls, GNUNET_PQ_result_spec_variable_size ("coin_ev", (void **) &rrc->coin_ev, &rrc->coin_ev_size), - TALER_PQ_result_spec_denom_sig ("ev_sig", - &rrc->coin_sig), + TALER_PQ_result_spec_blinded_denom_sig ("ev_sig", + &rrc->coin_sig), GNUNET_PQ_result_spec_end }; @@ -6309,7 +6309,7 @@ cleanup: struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i]; TALER_denom_pub_free (&rrc->denom_pub); - TALER_denom_sig_free (&rrc->coin_sig); + TALER_blinded_denom_sig_free (&rrc->coin_sig); GNUNET_free (rrc->coin_ev); } GNUNET_free (grctx.rrcs); diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index af567ba02..69acfa0b3 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -523,6 +523,34 @@ struct TALER_DenominationSignature }; +/** + * @brief Type for *blinded* denomination signatures for Taler. + * Must be unblinded before it becomes valid. + */ +struct TALER_BlindedDenominationSignature +{ + + /** + * Type of the signature. + */ + enum TALER_DenominationCipher cipher; + + /** + * Details, depending on @e cipher. + */ + union + { + + /** + * If we use #TALER_DENOMINATION_RSA in @a cipher. + */ + struct GNUNET_CRYPTO_RsaSignature *blinded_rsa_signature; + + } details; + +}; + + /** * @brief Type of public signing keys for verifying blindly signed coins. */ @@ -662,6 +690,16 @@ void TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); +/** + * Free internals of @a denom_sig, but not @a denom_sig itself. + * + * @param[in] denom_sig signature to free + */ +void +TALER_blinded_denom_sig_free ( + struct TALER_BlindedDenominationSignature *denom_sig); + + /** * Compute the hash of the given @a denom_pub. * @@ -697,6 +735,19 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst, const struct TALER_DenominationSignature *denom_src); +/** + * Make a (deep) copy of the given @a denom_src to + * @a denom_dst. + * + * @param[out] denom_dst target to copy to + * @param denom_str public key to copy + */ +void +TALER_blinded_denom_sig_deep_copy ( + struct TALER_BlindedDenominationSignature *denom_dst, + const struct TALER_BlindedDenominationSignature *denom_src); + + /** * Compare two denomination public keys. * @@ -1014,11 +1065,12 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, - const struct TALER_CoinPubHash *c_hash, - struct TALER_FreshCoin *coin); +TALER_planchet_to_coin ( + const struct TALER_DenominationPublicKey *dk, + const struct TALER_BlindedDenominationSignature *blind_sig, + const struct TALER_PlanchetSecretsP *ps, + const struct TALER_CoinPubHash *c_hash, + struct TALER_FreshCoin *coin); /* ****************** Refresh crypto primitives ************* */ @@ -1215,7 +1267,7 @@ TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *dh); * @return signature, the value inside the structure will be NULL on failure, * see @a ec for details about the failure */ -struct TALER_DenominationSignature +struct TALER_BlindedDenominationSignature TALER_CRYPTO_helper_denom_sign ( struct TALER_CRYPTO_DenominationHelper *dh, const struct TALER_DenominationHash *h_denom_pub, diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 6daa120d4..361956cbe 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1387,7 +1387,7 @@ typedef void (*TALER_EXCHANGE_Withdraw2Callback) ( void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig); + const struct TALER_BlindedDenominationSignature *blind_sig); /** diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index aa67092ee..17df75281 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -696,9 +696,9 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin { /** - * Our signature over the (blinded) coin. + * Our (blinded) signature over the (blinded) coin. */ - struct TALER_DenominationSignature sig; + struct TALER_BlindedDenominationSignature sig; /** * Hash of the denomination key (which coin was generated). @@ -1616,7 +1616,7 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin /** * Signature generated by the exchange over the coin (in blinded format). */ - struct TALER_DenominationSignature coin_sig; + struct TALER_BlindedDenominationSignature coin_sig; }; diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index e381a7a10..26df1f113 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -158,6 +158,21 @@ TALER_JSON_pack_denom_sig ( const struct TALER_DenominationSignature *sig); +/** + * Generate packer instruction for a JSON field of type + * blinded denomination signature (that needs to be + * unblinded before it becomes valid). + * + * @param name name of the field to add to the object + * @param sig signature + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_blinded_denom_sig ( + const char *name, + const struct TALER_BlindedDenominationSignature *sig); + + /** * Generate packer instruction for a JSON field of type * amount. @@ -327,6 +342,20 @@ TALER_JSON_spec_denom_sig (const char *field, struct TALER_DenominationSignature *sig); +/** + * Generate line in parser specification for a + * blinded denomination signature. + * + * @param field name of the field + * @param sig the blinded signature to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_denom_sig ( + const char *field, + struct TALER_BlindedDenominationSignature *sig); + + /** * The expected field stores a possibly internationalized string. * Internationalization means that there is another field "$name_i18n" diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 07057722a..6e69cdf6d 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -77,6 +77,18 @@ TALER_PQ_query_param_denom_sig ( const struct TALER_DenominationSignature *denom_sig); +/** + * Generate query parameter for a blinded denomination signature. Internally, + * the various attributes of the signature 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_denom_sig ( + const struct TALER_BlindedDenominationSignature *denom_sig); + + /** * Generate query parameter for a JSON object (stored as a string * in the DB). Note that @a x must really be a JSON object or array, @@ -168,6 +180,19 @@ TALER_PQ_result_spec_denom_sig (const char *name, struct TALER_DenominationSignature *denom_sig); +/** + * Blinded denomination signature expected. + * + * @param name name of the field in the table + * @param[out] denom_sig where to store the denomination signature + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blinded_denom_sig ( + const char *name, + struct TALER_BlindedDenominationSignature *denom_sig); + + /** * json_t expected. * diff --git a/src/json/json_helper.c b/src/json/json_helper.c index d509f4eff..1684e7f35 100644 --- a/src/json/json_helper.c +++ b/src/json/json_helper.c @@ -433,7 +433,7 @@ TALER_JSON_spec_relative_time (const char *name, * @param[out] spec where to write the data * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error */ -static int +static enum GNUNET_GenericReturnValue parse_denom_pub (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) @@ -528,7 +528,7 @@ TALER_JSON_spec_denom_pub (const char *field, * @param[out] spec where to write the data * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error */ -static int +static enum GNUNET_GenericReturnValue parse_denom_sig (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) @@ -613,6 +613,100 @@ TALER_JSON_spec_denom_sig (const char *field, } +/** + * Parse given JSON object to blinded denomination signature. + * + * @param cls closure, NULL + * @param root the json object representing data + * @param[out] spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static enum GNUNET_GenericReturnValue +parse_blinded_denom_sig (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr; + uint32_t cipher; + struct GNUNET_JSON_Specification dspec[] = { + GNUNET_JSON_spec_uint32 ("cipher", + &cipher), + GNUNET_JSON_spec_end () + }; + const char *emsg; + unsigned int eline; + + if (GNUNET_OK != + GNUNET_JSON_parse (root, + dspec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + denom_sig->cipher = (enum TALER_DenominationCipher) cipher; + switch (denom_sig->cipher) + { + case TALER_DENOMINATION_RSA: + { + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_rsa_signature ( + "blinded_rsa_signature", + &denom_sig->details.blinded_rsa_signature), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (root, + ispec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; + } + default: + GNUNET_break_op (0); + return GNUNET_SYSERR; + } +} + + +/** + * Cleanup data left from parsing denomination public key. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_blinded_denom_sig (void *cls, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr; + + TALER_blinded_denom_sig_free (denom_sig); +} + + +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_denom_sig ( + const char *field, + struct TALER_BlindedDenominationSignature *sig) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_blinded_denom_sig, + .cleaner = &clean_blinded_denom_sig, + .field = field, + .ptr = sig + }; + + return ret; +} + + /** * Closure for #parse_i18n_string. */ diff --git a/src/json/json_pack.c b/src/json/json_pack.c index 0d1c95708..59e3afb77 100644 --- a/src/json/json_pack.c +++ b/src/json/json_pack.c @@ -141,6 +141,32 @@ TALER_JSON_pack_denom_sig ( } +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_blinded_denom_sig ( + const char *name, + const struct TALER_BlindedDenominationSignature *sig) +{ + struct GNUNET_JSON_PackSpec ps = { + .field_name = name, + }; + + switch (sig->cipher) + { + case TALER_DENOMINATION_RSA: + ps.object + = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ("cipher", + TALER_DENOMINATION_RSA), + GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature", + sig->details.blinded_rsa_signature)); + break; + default: + GNUNET_assert (0); + } + return ps; +} + + struct GNUNET_JSON_PackSpec TALER_JSON_pack_amount (const char *name, const struct TALER_Amount *amount) diff --git a/src/lib/exchange_api_refreshes_reveal.c b/src/lib/exchange_api_refreshes_reveal.c index 0af37c021..c275e0a4d 100644 --- a/src/lib/exchange_api_refreshes_reveal.c +++ b/src/lib/exchange_api_refreshes_reveal.c @@ -137,12 +137,12 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh, const struct TALER_PlanchetSecretsP *fc; struct TALER_DenominationPublicKey *pk; json_t *jsonai; - struct GNUNET_CRYPTO_RsaSignature *blind_sig; + struct TALER_BlindedDenominationSignature blind_sig; struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinPubHash coin_hash; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_rsa_signature ("ev_sig", - &blind_sig), + TALER_JSON_spec_blinded_denom_sig ("ev_sig", + &blind_sig), GNUNET_JSON_spec_end () }; struct TALER_FreshCoin coin; @@ -170,17 +170,17 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh, &coin_hash); if (GNUNET_OK != TALER_planchet_to_coin (pk, - blind_sig, + &blind_sig, fc, &coin_hash, &coin)) { GNUNET_break_op (0); - GNUNET_CRYPTO_rsa_signature_free (blind_sig); + GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (outer_spec); return GNUNET_SYSERR; } - GNUNET_CRYPTO_rsa_signature_free (blind_sig); + GNUNET_JSON_parse_free (spec); sigs[i] = coin.sig; } GNUNET_JSON_parse_free (outer_spec); diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c index 8e00cfcdb..5e823ee6d 100644 --- a/src/lib/exchange_api_withdraw.c +++ b/src/lib/exchange_api_withdraw.c @@ -88,7 +88,7 @@ static void handle_reserve_withdraw_finished ( void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig) + const struct TALER_BlindedDenominationSignature *blind_sig) { struct TALER_EXCHANGE_WithdrawHandle *wh = cls; struct TALER_EXCHANGE_WithdrawResponse wr = { diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c index e001a3154..d50892e5b 100644 --- a/src/lib/exchange_api_withdraw2.c +++ b/src/lib/exchange_api_withdraw2.c @@ -99,10 +99,10 @@ static enum GNUNET_GenericReturnValue reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle *wh, const json_t *json) { - struct GNUNET_CRYPTO_RsaSignature *blind_sig; + struct TALER_BlindedDenominationSignature blind_sig; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_rsa_signature ("ev_sig", - &blind_sig), + TALER_JSON_spec_blinded_denom_sig ("ev_sig", + &blind_sig), GNUNET_JSON_spec_end () }; struct TALER_EXCHANGE_HttpResponse hr = { @@ -122,7 +122,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle *wh, /* signature is valid, return it to the application */ wh->cb (wh->cb_cls, &hr, - blind_sig); + &blind_sig); /* make sure callback isn't called again after return */ wh->cb = NULL; GNUNET_JSON_parse_free (spec); diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c index 3f51ddbe8..618877608 100644 --- a/src/pq/pq_query_helper.c +++ b/src/pq/pq_query_helper.c @@ -265,7 +265,7 @@ qconv_denom_sig (void *cls, const struct TALER_DenominationSignature *denom_sig = data; size_t tlen; size_t len; - uint32_t be; + uint32_t be[2]; char *buf; void *tbuf; @@ -273,7 +273,8 @@ qconv_denom_sig (void *cls, GNUNET_assert (1 == param_length); GNUNET_assert (scratch_length > 0); GNUNET_break (NULL == cls); - be = htonl ((uint32_t) denom_sig->cipher); + be[0] = htonl ((uint32_t) denom_sig->cipher); + be[1] = htonl (0x00); /* magic marker: unblinded */ switch (denom_sig->cipher) { case TALER_DENOMINATION_RSA: @@ -325,6 +326,95 @@ TALER_PQ_query_param_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_denom_sig (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_BlindedDenominationSignature *denom_sig = data; + size_t tlen; + size_t len; + uint32_t be[2]; + char *buf; + void *tbuf; + + (void) cls; + GNUNET_assert (1 == param_length); + GNUNET_assert (scratch_length > 0); + GNUNET_break (NULL == cls); + be[0] = htonl ((uint32_t) denom_sig->cipher); + be[1] = htonl (0x01); /* magic marker: blinded */ + switch (denom_sig->cipher) + { + case TALER_DENOMINATION_RSA: + tlen = GNUNET_CRYPTO_rsa_signature_encode ( + denom_sig->details.blinded_rsa_signature, + &tbuf); + break; + // TODO: add case for Clause-Schnorr + default: + GNUNET_assert (0); + } + len = tlen + sizeof (be); + buf = GNUNET_malloc (len); + memcpy (buf, + &be, + sizeof (be)); + switch (denom_sig->cipher) + { + case TALER_DENOMINATION_RSA: + memcpy (&buf[sizeof (be)], + tbuf, + tlen); + GNUNET_free (tbuf); + break; + // TODO: add case for Clause-Schnorr + 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_denom_sig ( + const struct TALER_BlindedDenominationSignature *denom_sig) +{ + struct GNUNET_PQ_QueryParam res = { + .conv = &qconv_blinded_denom_sig, + .data = denom_sig, + .num_params = 1 + }; + + return res; +} + + /** * Function called to convert input argument into SQL parameters. * diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c index 57bcf6dd3..2f570b6bb 100644 --- a/src/pq/pq_result_helper.c +++ b/src/pq/pq_result_helper.c @@ -630,7 +630,7 @@ extract_denom_sig (void *cls, size_t len; const char *res; int fnum; - uint32_t be; + uint32_t be[2]; (void) cls; fnum = PQfnumber (result, @@ -661,9 +661,14 @@ extract_denom_sig (void *cls, memcpy (&be, res, sizeof (be)); + if (0x00 != ntohl (be[1])) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } res += sizeof (be); len -= sizeof (be); - sig->cipher = ntohl (be); + sig->cipher = ntohl (be[0]); switch (sig->cipher) { case TALER_DENOMINATION_RSA: @@ -717,4 +722,122 @@ TALER_PQ_result_spec_denom_sig (const char *name, } +/** + * 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_denom_sig (void *cls, + PGresult *result, + int row, + const char *fname, + size_t *dst_size, + void *dst) +{ + struct TALER_BlindedDenominationSignature *sig = dst; + size_t len; + const char *res; + int fnum; + uint32_t be[2]; + + (void) cls; + 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 (0x01 != ntohl (be[1])) /* magic marker: blinded */ + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + res += sizeof (be); + len -= sizeof (be); + sig->cipher = ntohl (be[0]); + switch (sig->cipher) + { + case TALER_DENOMINATION_RSA: + sig->details.blinded_rsa_signature + = GNUNET_CRYPTO_rsa_signature_decode (res, + len); + if (NULL == sig->details.blinded_rsa_signature) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; + // FIXME: add CS case! + 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_denom_sig (void *cls, + void *rd) +{ + struct TALER_BlindedDenominationSignature *denom_sig = rd; + + (void) cls; + TALER_blinded_denom_sig_free (denom_sig); +} + + +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blinded_denom_sig ( + const char *name, + struct TALER_BlindedDenominationSignature *denom_sig) +{ + struct GNUNET_PQ_ResultSpec res = { + .conv = &extract_blinded_denom_sig, + .cleaner = &clean_blinded_denom_sig, + .dst = (void *) denom_sig, + .fname = name + }; + + return res; +} + + /* end of pq_result_helper.c */ diff --git a/src/util/crypto.c b/src/util/crypto.c index c7b459450..99744304b 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -212,21 +212,23 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, enum GNUNET_GenericReturnValue -TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, - const struct TALER_CoinPubHash *c_hash, - struct TALER_FreshCoin *coin) +TALER_planchet_to_coin ( + const struct TALER_DenominationPublicKey *dk, + const struct TALER_BlindedDenominationSignature *blind_sig, + const struct TALER_PlanchetSecretsP *ps, + const struct TALER_CoinPubHash *c_hash, + struct TALER_FreshCoin *coin) { struct TALER_DenominationSignature sig; - // FIXME-Gian/Lucien: this will be the bigger + // FIXME-Gian/Lucien: this may need a bigger // change, as you have the extra round trip // => to be discussed! GNUNET_assert (TALER_DENOMINATION_RSA == dk->cipher); + GNUNET_assert (TALER_DENOMINATION_RSA == blind_sig->cipher); sig.cipher = TALER_DENOMINATION_RSA; sig.details.rsa_signature - = TALER_rsa_unblind (blind_sig, + = TALER_rsa_unblind (blind_sig->details.blinded_rsa_signature, &ps->blinding_key.bks, dk->details.rsa_public_key); if (GNUNET_OK != diff --git a/src/util/crypto_helper_denom.c b/src/util/crypto_helper_denom.c index ba56a4e71..4dfd32fbd 100644 --- a/src/util/crypto_helper_denom.c +++ b/src/util/crypto_helper_denom.c @@ -541,7 +541,7 @@ TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *dh) } -struct TALER_DenominationSignature +struct TALER_BlindedDenominationSignature TALER_CRYPTO_helper_denom_sign ( struct TALER_CRYPTO_DenominationHelper *dh, const struct TALER_DenominationHash *h_denom_pub, @@ -549,8 +549,8 @@ TALER_CRYPTO_helper_denom_sign ( size_t msg_size, enum TALER_ErrorCode *ec) { - struct TALER_DenominationSignature ds = { - .details.rsa_signature = NULL + struct TALER_BlindedDenominationSignature ds = { + .details.blinded_rsa_signature = NULL }; { char buf[sizeof (struct TALER_CRYPTO_SignRequest) + msg_size]; @@ -652,7 +652,7 @@ TALER_CRYPTO_helper_denom_sign ( } *ec = TALER_EC_NONE; ds.cipher = TALER_DENOMINATION_RSA; - ds.details.rsa_signature = rsa_signature; + ds.details.blinded_rsa_signature = rsa_signature; return ds; } case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE: diff --git a/src/util/denom.c b/src/util/denom.c index 33b507639..8d6ddd5e7 100644 --- a/src/util/denom.c +++ b/src/util/denom.c @@ -169,6 +169,27 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig) } +void +TALER_blinded_denom_sig_free ( + struct TALER_BlindedDenominationSignature *denom_sig) +{ + switch (denom_sig->cipher) + { + case TALER_DENOMINATION_RSA: + if (NULL != denom_sig->details.blinded_rsa_signature) + { + GNUNET_CRYPTO_rsa_signature_free ( + denom_sig->details.blinded_rsa_signature); + denom_sig->details.blinded_rsa_signature = NULL; + } + return; + // TODO: add case for Clause-Schnorr + default: + GNUNET_assert (0); + } +} + + /** * Make a (deep) copy of the given @a denom_src to * @a denom_dst. @@ -214,13 +235,26 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst, } -/** - * Compare two denomination public keys. - * - * @param denom1 first key - * @param denom2 second key - * @return 0 if the keys are equal, otherwise -1 or 1 - */ +void +TALER_blinded_denom_sig_deep_copy ( + struct TALER_BlindedDenominationSignature *denom_dst, + const struct TALER_BlindedDenominationSignature *denom_src) +{ + *denom_dst = *denom_src; /* shallow copy */ + switch (denom_src->cipher) + { + case TALER_DENOMINATION_RSA: + denom_dst->details.blinded_rsa_signature + = GNUNET_CRYPTO_rsa_signature_dup ( + denom_src->details.blinded_rsa_signature); + return; + // TODO: add case for Clause-Schnorr + default: + GNUNET_assert (0); + } +} + + int TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1, const struct TALER_DenominationPublicKey *denom2)