Compare commits
2 Commits
2b85559c06
...
8fe127eb2e
Author | SHA1 | Date | |
---|---|---|---|
8fe127eb2e | |||
ffe4cc06aa |
@ -1 +1 @@
|
||||
Subproject commit b0dd85e8187f33a1f92dd5eb31082050d333e168
|
||||
Subproject commit 94b3d826de2aa442a985d03a52eaf526ef950d83
|
@ -285,6 +285,7 @@ check_commitment (struct RevealContext *rctx,
|
||||
* @param rctx context for the operation, partially built at this time
|
||||
* @param link_sigs_json link signatures in JSON format
|
||||
* @param new_denoms_h_json requests for fresh coins to be created
|
||||
* @param old_age_commitment_json age commitment that went into the withdrawal, maybe NULL
|
||||
* @param coin_evs envelopes of gamma-selected coins to be signed
|
||||
* @return MHD result code
|
||||
*/
|
||||
@ -293,6 +294,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
struct RevealContext *rctx,
|
||||
const json_t *link_sigs_json,
|
||||
const json_t *new_denoms_h_json,
|
||||
const json_t *old_age_commitment_json,
|
||||
const json_t *coin_evs)
|
||||
{
|
||||
unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
|
||||
@ -317,6 +319,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Parse denomination key hashes */
|
||||
for (unsigned int i = 0; i<num_fresh_coins; i++)
|
||||
{
|
||||
@ -443,6 +446,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse link signatures array */
|
||||
for (unsigned int i = 0; i<num_fresh_coins; i++)
|
||||
{
|
||||
@ -460,6 +464,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
-1);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||
|
||||
/* Check signature */
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_link_verify (
|
||||
@ -467,6 +472,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
&rctx->gamma_tp,
|
||||
&rrcs[i].coin_envelope_hash,
|
||||
&rctx->melt.session.coin.coin_pub,
|
||||
NULL, // TODO-oec: calculate the correct h_age_commitment
|
||||
&rrcs[i].orig_coin_link_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
@ -489,6 +495,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
rcd->coin_ev_size = rrc->coin_ev_size;
|
||||
rcd->dk = &dks[i]->denom_pub;
|
||||
}
|
||||
|
||||
rctx->dks = dks;
|
||||
rctx->rcds = rcds;
|
||||
if (GNUNET_OK !=
|
||||
@ -500,6 +507,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Creating %u signatures\n",
|
||||
(unsigned int) rctx->num_fresh_coins);
|
||||
|
||||
/* create fresh coin signatures */
|
||||
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
||||
{
|
||||
@ -520,8 +528,10 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Signatures ready, starting DB interaction\n");
|
||||
|
||||
/* Persist operation result in DB */
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
@ -577,11 +587,18 @@ cleanup:
|
||||
* revealed information is valid then returns the signed refreshed
|
||||
* coins.
|
||||
*
|
||||
* If the denomination has age restriction support, the array of EDDSA public
|
||||
* keys, one for each age group that was activated during the withdrawal
|
||||
* by the parent/ward, must be provided in old_age_commitment. The hash of
|
||||
* this array must be the same as the h_age_commitment of the persisted reveal
|
||||
* request.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param rctx context for the operation, partially built at this time
|
||||
* @param tp_json private transfer keys in JSON format
|
||||
* @param link_sigs_json link signatures in JSON format
|
||||
* @param new_denoms_h_json requests for fresh coins to be created
|
||||
* @param old_age_commitment_json array of EDDSA public keys in JSON, used for age restriction, maybe NULL
|
||||
* @param coin_evs envelopes of gamma-selected coins to be signed
|
||||
* @return MHD result code
|
||||
*/
|
||||
@ -591,6 +608,7 @@ handle_refreshes_reveal_json (struct MHD_Connection *connection,
|
||||
const json_t *tp_json,
|
||||
const json_t *link_sigs_json,
|
||||
const json_t *new_denoms_h_json,
|
||||
const json_t *old_age_commitment_json,
|
||||
const json_t *coin_evs)
|
||||
{
|
||||
unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
|
||||
@ -626,6 +644,19 @@ handle_refreshes_reveal_json (struct MHD_Connection *connection,
|
||||
"new_denoms/link_sigs");
|
||||
}
|
||||
|
||||
/* Sanity check of age commitment: If it was provided, it _must_ be an array
|
||||
* of the size the # of age groups */
|
||||
if (NULL != old_age_commitment_json
|
||||
&& TALER_extensions_age_restriction_num_groups () !=
|
||||
json_array_size (old_age_commitment_json))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_COMMITMENT_INVALID,
|
||||
"old_age_commitment");
|
||||
}
|
||||
|
||||
/* Parse transfer private keys array */
|
||||
for (unsigned int i = 0; i<num_tprivs; i++)
|
||||
{
|
||||
@ -649,6 +680,7 @@ handle_refreshes_reveal_json (struct MHD_Connection *connection,
|
||||
rctx,
|
||||
link_sigs_json,
|
||||
new_denoms_h_json,
|
||||
old_age_commitment_json,
|
||||
coin_evs);
|
||||
}
|
||||
|
||||
@ -662,6 +694,7 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
||||
json_t *transfer_privs;
|
||||
json_t *link_sigs;
|
||||
json_t *new_denoms_h;
|
||||
json_t *old_age_commitment = NULL;
|
||||
struct RevealContext rctx;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("transfer_pub",
|
||||
@ -674,6 +707,9 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
||||
&coin_evs),
|
||||
GNUNET_JSON_spec_json ("new_denoms_h",
|
||||
&new_denoms_h),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_json ("old_age_commitment",
|
||||
&old_age_commitment)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -735,6 +771,7 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
||||
transfer_privs,
|
||||
link_sigs,
|
||||
new_denoms_h,
|
||||
old_age_commitment,
|
||||
coin_evs);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return res;
|
||||
|
@ -830,6 +830,7 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",denoms.fee_refresh_frac"
|
||||
",old_coin_pub"
|
||||
",old_coin_sig"
|
||||
",h_age_commitment"
|
||||
",amount_with_fee_val"
|
||||
",amount_with_fee_frac"
|
||||
",noreveal_index"
|
||||
@ -6020,6 +6021,7 @@ postgres_get_melt (void *cls,
|
||||
uint64_t *melt_serial_id)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
bool h_age_commitment_is_null;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (rc),
|
||||
GNUNET_PQ_query_param_end
|
||||
@ -6036,6 +6038,10 @@ postgres_get_melt (void *cls,
|
||||
&melt->session.coin.coin_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
|
||||
&melt->session.coin_sig),
|
||||
GNUNET_PQ_result_spec_allow_null (
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_age_commitment",
|
||||
&melt->session.h_age_commitment),
|
||||
&h_age_commitment_is_null),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
|
||||
&melt->session.amount_with_fee),
|
||||
GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
|
||||
@ -6051,6 +6057,11 @@ postgres_get_melt (void *cls,
|
||||
"get_melt",
|
||||
params,
|
||||
rs);
|
||||
if (h_age_commitment_is_null)
|
||||
memset (&melt->session.h_age_commitment,
|
||||
0,
|
||||
sizeof(melt->session.h_age_commitment));
|
||||
|
||||
melt->session.rc = *rc;
|
||||
return qs;
|
||||
}
|
||||
|
@ -23,6 +23,19 @@
|
||||
#include "taler_extensions.h"
|
||||
#include "stdint.h"
|
||||
|
||||
/**
|
||||
* Carries all the information we need for age restriction
|
||||
*/
|
||||
struct age_restriction_config
|
||||
{
|
||||
struct TALER_AgeMask mask;
|
||||
size_t num_groups;
|
||||
};
|
||||
|
||||
/**
|
||||
* Global config for this extension
|
||||
*/
|
||||
static struct age_restriction_config _config = {0};
|
||||
|
||||
/**
|
||||
* @param groups String representation of the age groups. Must be of the form
|
||||
@ -146,6 +159,9 @@ age_restriction_disable (
|
||||
json_decref (this->config_json);
|
||||
this->config_json = NULL;
|
||||
}
|
||||
|
||||
_config.mask.mask = 0;
|
||||
_config.num_groups = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -197,7 +213,6 @@ age_restriction_load_taler_config (
|
||||
|
||||
|
||||
mask.mask = TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_MASK;
|
||||
|
||||
ret = GNUNET_OK;
|
||||
|
||||
if (groups != NULL)
|
||||
@ -208,7 +223,11 @@ age_restriction_load_taler_config (
|
||||
}
|
||||
|
||||
if (GNUNET_OK == ret)
|
||||
this->config = (void *) (size_t) mask.mask;
|
||||
{
|
||||
_config.mask.mask = mask.mask;
|
||||
_config.num_groups = __builtin_popcount (mask.mask);
|
||||
this->config = &_config;
|
||||
}
|
||||
|
||||
GNUNET_free (groups);
|
||||
return ret;
|
||||
@ -223,12 +242,12 @@ age_restriction_load_taler_config (
|
||||
static enum GNUNET_GenericReturnValue
|
||||
age_restriction_load_json_config (
|
||||
struct TALER_Extension *this,
|
||||
json_t *config)
|
||||
json_t *jconfig)
|
||||
{
|
||||
struct TALER_AgeMask mask = {0};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
ret = TALER_JSON_parse_agemask (config, &mask);
|
||||
ret = TALER_JSON_parse_agemask (jconfig, &mask);
|
||||
if (GNUNET_OK != ret)
|
||||
return ret;
|
||||
|
||||
@ -239,16 +258,15 @@ age_restriction_load_json_config (
|
||||
if (TALER_Extension_AgeRestriction != this->type)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
if (NULL != this->config)
|
||||
GNUNET_free (this->config);
|
||||
|
||||
this->config = GNUNET_malloc (sizeof(struct TALER_AgeMask));
|
||||
GNUNET_memcpy (this->config, &mask, sizeof(struct TALER_AgeMask));
|
||||
_config.mask.mask = mask.mask;
|
||||
_config.num_groups = __builtin_popcount (mask.mask);
|
||||
this->config = &_config;
|
||||
|
||||
if (NULL != this->config_json)
|
||||
json_decref (this->config_json);
|
||||
|
||||
this->config_json = config;
|
||||
this->config_json = jconfig;
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
@ -263,7 +281,6 @@ json_t *
|
||||
age_restriction_config_to_json (
|
||||
const struct TALER_Extension *this)
|
||||
{
|
||||
struct TALER_AgeMask mask;
|
||||
char *mask_str;
|
||||
json_t *conf;
|
||||
|
||||
@ -275,8 +292,7 @@ age_restriction_config_to_json (
|
||||
return json_copy (this->config_json);
|
||||
}
|
||||
|
||||
mask.mask = (uint32_t) (size_t) this->config;
|
||||
mask_str = TALER_age_mask_to_string (&mask);
|
||||
mask_str = TALER_age_mask_to_string (&_config.mask);
|
||||
conf = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_string ("age_groups", mask_str)
|
||||
);
|
||||
@ -318,4 +334,18 @@ struct TALER_Extension _extension_age_restriction = {
|
||||
.load_taler_config = &age_restriction_load_taler_config,
|
||||
};
|
||||
|
||||
bool
|
||||
TALER_extensions_age_restriction_enabled ()
|
||||
{
|
||||
return (0 != _config.mask.mask);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
TALER_extensions_age_restriction_num_groups ()
|
||||
{
|
||||
return _config.num_groups;
|
||||
}
|
||||
|
||||
|
||||
/* end of extension_age_restriction.c */
|
||||
|
@ -311,9 +311,11 @@ struct TALER_AgeHash
|
||||
struct GNUNET_ShortHashCode shash;
|
||||
};
|
||||
|
||||
bool
|
||||
TALER_AgeHash_isZero (
|
||||
const struct TALER_AgeHash *hash);
|
||||
extern const struct TALER_AgeHash TALER_AgeHash_zeroHash;
|
||||
#define TALER_AgeHash_isZero(ph) ((NULL == ph) || \
|
||||
(0 == memcmp (ph, \
|
||||
&TALER_AgeHash_zeroHash, \
|
||||
sizeof(struct TALER_AgeHash))))
|
||||
|
||||
/**
|
||||
* @brief Type of public keys for Taler coins. The same key material is used
|
||||
@ -1809,6 +1811,7 @@ TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub,
|
||||
* @param transfer_pub transfer public key
|
||||
* @param h_coin_ev hash of the coin envelope
|
||||
* @param old_coin_pub old coin key that the link signature is for
|
||||
* @param h_age_commitment hash of age commitment. Maybe NULL, if not applicable.
|
||||
* @param coin_sig resulting signature
|
||||
* @return #GNUNET_OK if the signature is valid
|
||||
*/
|
||||
@ -1818,6 +1821,7 @@ TALER_wallet_link_verify (
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub,
|
||||
const struct TALER_BlindedCoinHash *h_coin_ev,
|
||||
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
||||
const struct TALER_AgeHash *h_age_commitment,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig);
|
||||
|
||||
|
||||
|
@ -1260,6 +1260,13 @@ struct TALER_EXCHANGEDB_Refresh
|
||||
*/
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
|
||||
/**
|
||||
* Hash of the age commitment used to sign the coin, if age restriction was
|
||||
* applicable to the denomination. May be all zeroes if no age restriction
|
||||
* applies.
|
||||
*/
|
||||
struct TALER_AgeHash h_age_commitment;
|
||||
|
||||
/**
|
||||
* Refresh commitment this coin is melted into.
|
||||
*/
|
||||
@ -1306,8 +1313,9 @@ struct TALER_EXCHANGEDB_MeltListEntry
|
||||
struct TALER_DenominationHash h_denom_pub;
|
||||
|
||||
/**
|
||||
* Hash of the age commitment used to sign the coin. May be all zeroes if no
|
||||
* age restriction applies.
|
||||
* Hash of the age commitment used to sign the coin, if age restriction was
|
||||
* applicable to the denomination. May be all zeroes if no age restriction
|
||||
* applies.
|
||||
*/
|
||||
struct TALER_AgeHash h_age_commitment;
|
||||
|
||||
|
@ -221,6 +221,18 @@ char *
|
||||
TALER_age_mask_to_string (
|
||||
const struct TALER_AgeMask *mask);
|
||||
|
||||
/**
|
||||
* Returns true when age restriction is enabled
|
||||
*/
|
||||
bool
|
||||
TALER_extensions_age_restriction_enabled ();
|
||||
|
||||
/**
|
||||
* Returns the amount of age groups defined. 0 means no age restriction
|
||||
* enabled.
|
||||
*/
|
||||
size_t
|
||||
TALER_extensions_age_restriction_num_groups ();
|
||||
|
||||
/*
|
||||
* TODO: Add Peer2Peer Extension
|
||||
|
@ -414,6 +414,11 @@ struct TALER_LinkDataPS
|
||||
*/
|
||||
struct TALER_TransferPublicKeyP transfer_pub;
|
||||
|
||||
/**
|
||||
* Hash of the age commitment, if applicable. Can be all zero
|
||||
*/
|
||||
struct TALER_AgeHash h_age_commitment;
|
||||
|
||||
/**
|
||||
* Hash of the blinded new coin.
|
||||
*/
|
||||
|
@ -105,6 +105,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
};
|
||||
struct TALER_TransferSecretP secret;
|
||||
struct TALER_PlanchetSecretsP fc;
|
||||
struct TALER_AgeHash h_age_commitment = {0}; // TODO, see below.
|
||||
|
||||
/* parse reply */
|
||||
if (GNUNET_OK !=
|
||||
@ -156,11 +157,21 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
pd.coin_ev_size,
|
||||
&coin_envelope_hash.hash);
|
||||
|
||||
/*
|
||||
* TODO-oec: Derive the age commitment vector and hash it into
|
||||
* h_age_commitment.
|
||||
* Questions:
|
||||
* - Where do we get the information about the support for age
|
||||
* restriction of the denomination?
|
||||
* - Where do we get the information bout the previous coin's age groups?
|
||||
*/
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_link_verify (&pd.denom_pub_hash,
|
||||
trans_pub,
|
||||
&coin_envelope_hash,
|
||||
&old_coin_pub,
|
||||
&h_age_commitment,
|
||||
&link_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
|
@ -25,6 +25,10 @@
|
||||
#include "taler_util.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
/**
|
||||
* Used in TALER_AgeHash_isZero for comparison
|
||||
*/
|
||||
const struct TALER_AgeHash TALER_AgeHash_zeroHash = {0};
|
||||
|
||||
/**
|
||||
* Function called by libgcrypt on serious errors.
|
||||
@ -352,13 +356,4 @@ TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TALER_AgeHash_isZero (
|
||||
const struct TALER_AgeHash *hash)
|
||||
{
|
||||
static struct TALER_AgeHash zeroAgeHash = {0};
|
||||
return (0 == memcmp (hash, &zeroAgeHash, sizeof(struct TALER_AgeHash)));
|
||||
}
|
||||
|
||||
|
||||
/* end of crypto.c */
|
||||
|
@ -135,6 +135,7 @@ TALER_wallet_link_verify (
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub,
|
||||
const struct TALER_BlindedCoinHash *h_coin_ev,
|
||||
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
||||
const struct TALER_AgeHash *h_age_commitment,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig)
|
||||
{
|
||||
struct TALER_LinkDataPS ldp = {
|
||||
@ -145,6 +146,13 @@ TALER_wallet_link_verify (
|
||||
.coin_envelope_hash = *h_coin_ev
|
||||
};
|
||||
|
||||
if (NULL == h_age_commitment)
|
||||
memset (&ldp.h_age_commitment,
|
||||
0,
|
||||
sizeof(*h_age_commitment));
|
||||
else
|
||||
ldp.h_age_commitment = *h_age_commitment;
|
||||
|
||||
return
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
|
||||
&ldp,
|
||||
|
Loading…
Reference in New Issue
Block a user