Compare commits

...

4 Commits

Author SHA1 Message Date
1b1a6c142a
[WIP] hash and signature verification of /keys works again
- Hashes of (normal) denominations and age-restricted denominations are
  calculated seperately
- The hash of the age-restricted ones will then be added to the other
  hash
- The total hash is signed/verified

So far: test_exchange_api runs, including withdraw_age!

However, test_auditor_api fails and another is in a endless loop!
2022-02-08 00:00:24 +01:00
632d17f642
[WIP] moving towards withdrawal with age restriction
Age_mask now taken into account when denominations are being setup.
However, tests fail, because denoms can't be found!?  Probably because
on initial generation of the denominations, the age mask is not setup,
yet, because age restriction hasn't been enabled yet!?
2022-02-07 18:39:58 +01:00
d02b5e213a
[WIP] exchangedb adjustments for denominations
- all prepared statements re: denominations now handle age_mask

- signatures parameters adjusted.

Now compiles and Tests run but fail.

- good: we find denoms[] and age_restricted_denoms[] filled correctly in
  output to /keys

- bad: fails at exchange_api_handle.c:882, signature verification of
  denom.
2022-02-07 13:56:25 +01:00
f8b1c3f8db
Debugging session of withdraw with age restriction 2022-02-07 09:06:51 +01:00
20 changed files with 260 additions and 94 deletions

View File

@ -152,6 +152,10 @@ static char *currency;
*/
static char *CFG_exchange_url;
/**
* If age restriction is enabled, the age mask to be used
*/
static struct TALER_AgeMask age_mask = {0};
/**
* A subcommand supported by this program.
@ -3037,6 +3041,7 @@ do_show (char *const *args)
keys = parse_keys_input ("show");
if (NULL == keys)
return;
if (GNUNET_OK !=
load_offline_key (GNUNET_NO))
return;
@ -3197,6 +3202,43 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
}
/**
* Looks up the AGE_RESTRICTED setting for a denomination in the config and
* returns the age restriction (mask) accordingly.
*
* @param section_name Section in the configuration for the particular
* denomination.
*/
static struct TALER_AgeMask
load_age_mask (const char*section_name)
{
static const struct TALER_AgeMask null_mask = {0};
enum GNUNET_GenericReturnValue ret;
if (age_mask.mask == 0)
return null_mask;
if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value (
kcfg,
section_name,
"AGE_RESTRICTED")))
return null_mask;
ret = GNUNET_CONFIGURATION_get_value_yesno (kcfg,
section_name,
"AGE_RESTRICTED");
if (GNUNET_YES == ret)
return age_mask;
if (GNUNET_SYSERR == ret)
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
section_name,
"AGE_RESTRICTED",
"Value must be YES or NO\n");
return null_mask;
}
/**
* Sign @a denomkeys with offline key.
*
@ -3285,7 +3327,10 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
duration = GNUNET_TIME_absolute_get_difference (
stamp_start.abs_time,
stamp_expire_withdraw.abs_time);
// FIXME-Oec: setup age mask here?
/* Load the age mask, if applicable to this denomination */
denom_pub.age_mask = load_age_mask (section_name);
TALER_denom_pub_hash (&denom_pub,
&h_denom_pub);
switch (denom_pub.cipher)
@ -3519,14 +3564,6 @@ do_extensions_show (char *const *args)
json_t *exts = json_object ();
const struct TALER_Extension *it;
TALER_extensions_init ();
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"error while loading taler config for extensions\n");
return;
}
for (it = TALER_extensions_get_head ();
NULL != it;
it = it->next)
@ -3780,6 +3817,17 @@ run (void *cls,
global_ret = EXIT_NOTCONFIGURED;
return;
}
/* load age mask, if age restriction is enabled */
TALER_extensions_init ();
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"error while loading taler config for extensions\n");
return;
}
age_mask = TALER_extensions_age_restriction_ageMask ();
ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
&rc);
rc = GNUNET_CURL_gnunet_rc_create (ctx);

View File

@ -157,6 +157,12 @@ TEH_extensions_init ()
it = it->next)
extension_update_event_cb (NULL, &it->type, sizeof(it->type));
/* FIXME: shall we load the extensions from the config right away?
* We do have to for now, as otherwise denominations with age restriction
* will not have the age mask set right upon initial generation.
*/
TALER_extensions_load_taler_config (TEH_cfg);
return GNUNET_OK;
}

View File

@ -743,43 +743,30 @@ static struct TALER_AgeMask
load_age_mask (const char*section_name)
{
static const struct TALER_AgeMask null_mask = {0};
struct TALER_AgeMask age_mask = {0};
/* TODO: optimize by putting this into global? */
const struct TALER_Extension *age_ext =
TALER_extensions_get_by_type (TALER_Extension_AgeRestriction);
// Get the age mask from the extension, if configured
/* TODO: optimize by putting this into global? */
if (TALER_extensions_is_enabled (age_ext))
age_mask = *(struct TALER_AgeMask *) age_ext->config;
enum GNUNET_GenericReturnValue ret;
struct TALER_AgeMask age_mask = TALER_extensions_age_restriction_ageMask ();
if (age_mask.mask == 0)
{
/* Age restriction support is not enabled. Ignore the AGE_RESTRICTED field
* for the particular denomination and simply return the null_mask
*/
return null_mask;
}
if (GNUNET_OK == (GNUNET_CONFIGURATION_have_value (
if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value (
TEH_cfg,
section_name,
"AGE_RESTRICTED")))
{
enum GNUNET_GenericReturnValue ret;
if (GNUNET_SYSERR == (ret = GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg,
section_name,
"AGE_RESTRICTED")))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
section_name,
"AGE_RESTRICTED",
"Value must be YES or NO\n");
return null_mask;
}
}
return null_mask;
return age_mask;
ret = GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg,
section_name,
"AGE_RESTRICTED");
if (GNUNET_YES == ret)
return age_mask;
if (GNUNET_SYSERR == ret)
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
section_name,
"AGE_RESTRICTED",
"Value must be YES or NO\n");
return null_mask;
}
@ -1187,6 +1174,8 @@ denomination_info_cb (
dk->meta = *meta;
dk->master_sig = *master_sig;
dk->recoup_possible = recoup_possible;
dk->denom_pub.age_mask = meta->age_mask;
GNUNET_assert (
GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (ksh->denomkey_map,
@ -1601,7 +1590,7 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
* @a recoup and @a denoms.
*
* @param[in,out] ksh key state handle we build @a krd for
* @param[in] denom_keys_hash hash over all the denominatoin keys in @a denoms
* @param[in] denom_keys_hash hash over all the denominatoin keys in @a denoms and age_restricted_denoms
* @param last_cpd timestamp to use
* @param signkeys list of sign keys to return
* @param recoup list of revoked keys to return
@ -1771,7 +1760,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
GNUNET_assert (0 == r);
}
// Special case for age restrictions: if enabled, provide the lits of
// Special case for age restrictions: if enabled, provide the list of
// age-restricted denominations.
if (age_restriction_enabled &&
NULL != age_restricted_denoms)
@ -1857,9 +1846,11 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
json_t *age_restricted_denoms = NULL;
struct GNUNET_TIME_Timestamp last_cpd;
struct GNUNET_CONTAINER_Heap *heap;
struct GNUNET_HashContext *hash_context;
struct GNUNET_HashContext *hash_context = NULL;
struct GNUNET_HashContext *hash_context_restricted = NULL;
bool age_restriction_active =
TALER_extensions_is_enabled_type (TALER_Extension_AgeRestriction);
bool have_age_restricted_denoms = false;
sctx.signkeys = json_array ();
GNUNET_assert (NULL != sctx.signkeys);
@ -1884,19 +1875,24 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
= GNUNET_TIME_relative_min (dkc.min_dk_frequency,
sctx.min_sk_frequency);
}
denoms = json_array ();
GNUNET_assert (NULL != denoms);
hash_context = GNUNET_CRYPTO_hash_context_start ();
// If age restriction is enabled, initialize the array of age restricted denoms.
/* TODO: optimize by putting this into global? */
/* If age restriction is enabled, initialize the array of age restricted
denoms and prepare a hash for them, separate from the others. We will join
those hashes afterwards.*/
if (age_restriction_active)
{
age_restricted_denoms = json_array ();
GNUNET_assert (NULL != age_restricted_denoms);
hash_context_restricted = GNUNET_CRYPTO_hash_context_start ();
}
last_cpd = GNUNET_TIME_UNIT_ZERO_TS;
hash_context = GNUNET_CRYPTO_hash_context_start ();
{
struct TEH_DenominationKey *dk;
@ -1938,14 +1934,14 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
return GNUNET_SYSERR;
}
}
last_cpd = dk->meta.start;
GNUNET_CRYPTO_hash_context_read (hash_context,
&dk->h_denom_pub,
sizeof (struct GNUNET_HashCode));
{
json_t *denom;
json_t *array;
struct GNUNET_HashContext *hc;
denom =
GNUNET_JSON_PACK (
@ -1972,19 +1968,25 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
TALER_JSON_pack_amount ("fee_refund",
&dk->meta.fee_refund));
/* Put the denom into the correct array - denoms or age_restricted_denoms -
* depending on the settings and the properties of the denomination */
/* Put the denom into the correct array depending on the settings and
* the properties of the denomination. Also, we build up the right
* hash for the corresponding array. */
if (age_restriction_active &&
(0 != dk->denom_pub.age_mask.mask))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"got agerestricted denom %p with mask %d\n",
&dk->denom_pub,
dk->denom_pub.age_mask.mask);
have_age_restricted_denoms = true;
array = age_restricted_denoms;
hc = hash_context_restricted;
}
else
{
array = denoms;
hc = hash_context;
}
GNUNET_CRYPTO_hash_context_read (hc,
&dk->h_denom_pub,
sizeof (struct GNUNET_HashCode));
GNUNET_assert (
0 ==
@ -2000,8 +2002,21 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{
struct GNUNET_HashCode hc;
/* If age restriction is active and we had at least one denomination of
* that sort, we simply add the hash of all age restricted denominations at
* the end of the others. */
if (age_restriction_active && have_age_restricted_denoms)
{
struct GNUNET_HashCode hcr;
GNUNET_CRYPTO_hash_context_finish (hash_context_restricted, &hcr);
GNUNET_CRYPTO_hash_context_read (hash_context,
&hcr,
sizeof (struct GNUNET_HashCode));
}
GNUNET_CRYPTO_hash_context_finish (hash_context,
&hc);
if (GNUNET_OK !=
create_krd (ksh,
&hc,
@ -2672,7 +2687,9 @@ load_extension_data (const char *section_name,
TEH_currency);
return GNUNET_SYSERR;
}
meta->age_restrictions = load_age_mask (section_name);
meta->age_mask = load_age_mask (section_name);
return GNUNET_OK;
}
@ -2799,7 +2816,7 @@ add_future_denomkey_cb (void *cls,
struct FutureBuilderContext *fbc = cls;
struct HelperDenomination *hd = value;
struct TEH_DenominationKey *dk;
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
dk = GNUNET_CONTAINER_multihashmap_get (fbc->ksh->denomkey_map,
h_denom_pub);

View File

@ -31,7 +31,6 @@
#include "taler_extensions.h"
#include "taler_dbevents.h"
/**
* Extension carries the necessary data for a particular extension.
*
@ -295,6 +294,10 @@ TEH_handler_management_post_extensions (
NULL,
0);
/* FIXME-oec. Because of a change of extensions, the key might */
TEH_keys_update_states ();
CLEANUP:
for (unsigned int i = 0; i < sec.num_extensions; i++)
{

View File

@ -204,6 +204,7 @@ add_keys (void *cls,
TALER_denom_pub_free (&denom_pub);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (is_active)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -211,6 +212,7 @@ add_keys (void *cls,
GNUNET_h2s (&d->h_denom_pub.hash));
continue; /* skip, already known */
}
qs = TEH_plugin->add_denomination_key (
TEH_plugin->cls,
&d->h_denom_pub,

View File

@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS denominations
(denominations_serial BIGSERIAL UNIQUE
,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!)
,age_restrictions INT4 NOT NULL DEFAULT (0)
,age_mask INT4 NOT NULL DEFAULT (0)
,denom_pub BYTEA NOT NULL
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
,valid_from INT8 NOT NULL
@ -47,7 +47,7 @@ COMMENT ON TABLE denominations
IS 'Main denominations table. All the valid denominations the exchange knows about.';
COMMENT ON COLUMN denominations.denom_type
IS 'determines cipher type for blind signatures used with this denomination; 0 is for RSA';
COMMENT ON COLUMN denominations.age_restrictions
COMMENT ON COLUMN denominations.age_mask
IS 'bitmask with the age restrictions that are being used for this denomination; 0 if denomination does not support the use of age restrictions';
COMMENT ON COLUMN denominations.denominations_serial
IS 'needed for exchange-auditor replication logic';

View File

@ -231,10 +231,11 @@ prepare_statements (struct PostgresClosure *pg)
",fee_refresh_frac"
",fee_refund_val"
",fee_refund_frac"
",age_mask"
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
" $11, $12, $13, $14, $15, $16, $17);",
17),
" $11, $12, $13, $14, $15, $16, $17, $18);",
18),
/* Used in #postgres_iterate_denomination_info() */
GNUNET_PQ_make_prepare (
"denomination_iterate",
@ -255,6 +256,7 @@ prepare_statements (struct PostgresClosure *pg)
",fee_refund_val"
",fee_refund_frac"
",denom_pub"
",age_mask"
" FROM denominations;",
0),
/* Used in #postgres_iterate_denominations() */
@ -278,6 +280,7 @@ prepare_statements (struct PostgresClosure *pg)
",fee_refund_val"
",fee_refund_frac"
",denom_pub"
",age_mask"
" FROM denominations"
" LEFT JOIN "
" denomination_revocations USING (denominations_serial);",
@ -341,6 +344,7 @@ prepare_statements (struct PostgresClosure *pg)
",fee_refresh_frac"
",fee_refund_val"
",fee_refund_frac"
",age_mask"
" FROM denominations"
" WHERE denom_pub_hash=$1;",
1),
@ -2071,7 +2075,6 @@ prepare_statements (struct PostgresClosure *pg)
"SELECT"
" denominations_serial AS serial"
",denom_type"
",age_restrictions"
",denom_pub"
",master_sig"
",valid_from"
@ -2088,6 +2091,7 @@ prepare_statements (struct PostgresClosure *pg)
",fee_refresh_frac"
",fee_refund_val"
",fee_refund_frac"
",age_mask"
" FROM denominations"
" WHERE denominations_serial > $1"
" ORDER BY denominations_serial ASC;",
@ -2390,10 +2394,11 @@ prepare_statements (struct PostgresClosure *pg)
",fee_refresh_frac"
",fee_refund_val"
",fee_refund_frac"
",age_mask"
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
" $11, $12, $13, $14, $15, $16, $17, $18);",
18),
" $11, $12, $13, $14, $15, $16, $17, $18, $19);",
19),
GNUNET_PQ_make_prepare (
"insert_into_table_denomination_revocations",
"INSERT INTO denomination_revocations"
@ -3096,9 +3101,12 @@ postgres_insert_denomination_info (
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_deposit),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refresh),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refund),
GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.mask),
GNUNET_PQ_query_param_end
};
GNUNET_assert (denom_pub->age_mask.mask == issue->age_mask.mask);
GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
GNUNET_TIME_timestamp_ntoh (
issue->properties.start).abs_time));
@ -3172,6 +3180,8 @@ postgres_get_denomination_info (
&issue->properties.fee_refresh),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
&issue->properties.fee_refund),
GNUNET_PQ_result_spec_uint32 ("age_mask",
&issue->age_mask.mask),
GNUNET_PQ_result_spec_end
};
@ -3258,12 +3268,15 @@ domination_cb_helper (void *cls,
&issue.properties.fee_refund),
TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub),
GNUNET_PQ_result_spec_uint32 ("age_mask",
&issue.age_mask.mask),
GNUNET_PQ_result_spec_end
};
memset (&issue.properties.master,
0,
sizeof (issue.properties.master));
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
@ -3272,6 +3285,13 @@ domination_cb_helper (void *cls,
GNUNET_break (0);
return;
}
/* Unfortunately we have to carry the age mask in both, the
* TALER_DenominationPublicKey and
* TALER_EXCHANGEDB_DenominationKeyInformationP at different times.
* Here we use _both_ so let's make sure the values are the same. */
denom_pub.age_mask = issue.age_mask;
issue.properties.purpose.size
= htonl (sizeof (struct TALER_DenominationKeyValidityPS));
issue.properties.purpose.purpose
@ -3357,10 +3377,10 @@ dominations_cb_helper (void *cls,
for (unsigned int i = 0; i<num_results; i++)
{
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
struct TALER_DenominationPublicKey denom_pub;
struct TALER_MasterSignatureP master_sig;
struct TALER_DenominationHash h_denom_pub;
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
struct TALER_DenominationPublicKey denom_pub = {0};
struct TALER_MasterSignatureP master_sig = {0};
struct TALER_DenominationHash h_denom_pub = {0};
bool revoked;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("master_sig",
@ -3387,6 +3407,8 @@ dominations_cb_helper (void *cls,
&meta.fee_refund),
TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub),
GNUNET_PQ_result_spec_uint32 ("age_mask",
&meta.age_mask.mask),
GNUNET_PQ_result_spec_end
};
@ -3398,6 +3420,10 @@ dominations_cb_helper (void *cls,
GNUNET_break (0);
return;
}
/* make sure the mask information is the same */
denom_pub.age_mask = meta.age_mask;
TALER_denom_pub_hash (&denom_pub,
&h_denom_pub);
dic->cb (dic->cb_cls,
@ -10193,6 +10219,8 @@ postgres_lookup_denomination_key (
&meta->fee_refresh),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
&meta->fee_refund),
GNUNET_PQ_result_spec_uint32 ("age_mask",
&meta->age_mask.mask),
GNUNET_PQ_result_spec_end
};
@ -10236,6 +10264,7 @@ postgres_add_denomination_key (
TALER_PQ_query_param_amount (&meta->fee_deposit),
TALER_PQ_query_param_amount (&meta->fee_refresh),
TALER_PQ_query_param_amount (&meta->fee_refund),
GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask),
GNUNET_PQ_query_param_end
};

View File

@ -224,6 +224,9 @@ age_restriction_load_taler_config (
if (GNUNET_OK == ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"setting age mask to %x with #groups: %d\n", mask.mask,
__builtin_popcount (mask.mask) - 1);
_config.mask.mask = mask.mask;
_config.num_groups = __builtin_popcount (mask.mask) - 1; /* no underflow, first bit always set */
this->config = &_config;
@ -277,6 +280,10 @@ age_restriction_load_json_config (
this->config_json = jconfig;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"loaded new age restriction config with age groups: %s\n",
TALER_age_mask_to_string (&mask));
return GNUNET_OK;
}
@ -350,6 +357,13 @@ TALER_extensions_age_restriction_enabled ()
}
struct TALER_AgeMask
TALER_extensions_age_restriction_ageMask ()
{
return _config.mask;
}
size_t
TALER_extensions_age_restriction_num_groups ()
{

View File

@ -159,13 +159,6 @@ struct TALER_EXCHANGE_DenomPublicKey
* revoked by the exchange.
*/
bool revoked;
/**
* If age_mask non-zero, the denomination is age-restricted, with the age
* groups as defined in the mask.
*/
struct TALER_AgeMask age_mask;
bool age_restricted;
};

View File

@ -70,6 +70,12 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP
* Signed properties of the denomination key.
*/
struct TALER_DenominationKeyValidityPS properties;
/**
* If denomination was setup for age restriction, non-zero age mask.
* Note that the mask is not part of the signature.
*/
struct TALER_AgeMask age_mask;
};
@ -643,7 +649,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
* A value of 0 means that the denomination does not support the extension for
* age-restriction.
*/
struct TALER_AgeMask age_restrictions;
struct TALER_AgeMask age_mask;
};

View File

@ -238,6 +238,13 @@ TALER_age_mask_to_string (
bool
TALER_extensions_age_restriction_enabled ();
/**
* Returns the currently set age mask
*/
struct TALER_AgeMask
TALER_extensions_age_restriction_ageMask ();
/**
* Returns the amount of age groups defined. 0 means no age restriction
* enabled.

View File

@ -67,7 +67,7 @@
/**
* Set to 1 for extra debug logging.
*/
#define DEBUG 1 /* FIXME-oec */
#define DEBUG 0
/**
* Log error related to CURL operations.
@ -667,7 +667,9 @@ decode_keys_json (const json_t *resp_obj,
enum TALER_EXCHANGE_VersionCompatibility *vc)
{
struct TALER_ExchangeSignatureP sig;
struct GNUNET_HashContext *hash_context;
struct GNUNET_HashContext *hash_context = NULL;
struct GNUNET_HashContext *hash_context_restricted = NULL;
bool have_age_restricted_denom = false;
struct TALER_ExchangePublicKeyP pub;
const char *currency;
struct GNUNET_JSON_Specification mspec[] = {
@ -746,7 +748,6 @@ decode_keys_json (const json_t *resp_obj,
key_data->version = GNUNET_strdup (ver);
}
hash_context = NULL;
EXITIF (GNUNET_OK !=
GNUNET_JSON_parse (resp_obj,
(check_sig) ? mspec : &mspec[2],
@ -766,7 +767,10 @@ decode_keys_json (const json_t *resp_obj,
/* parse the master public key and issue date of the response */
if (check_sig)
{
hash_context = GNUNET_CRYPTO_hash_context_start ();
hash_context_restricted = GNUNET_CRYPTO_hash_context_start ();
}
/* parse the signing keys */
{
@ -829,6 +833,9 @@ decode_keys_json (const json_t *resp_obj,
EXITIF (GNUNET_OK !=
TALER_extensions_load_json_config (extensions));
}
/* 4. assuming we might have now a new value for age_mask, set it in key_data */
key_data->age_mask = TALER_extensions_age_restriction_ageMask ();
}
/* parse the denomination keys, merging with the
@ -839,10 +846,15 @@ decode_keys_json (const json_t *resp_obj,
*/
struct
{ char *name;
struct GNUNET_HashContext *hc;
bool is_optional_age_restriction;}
hive[2] = {
{ "denoms", false },
{ "age_restricted_denoms", true }
{ "denoms",
hash_context,
false },
{ "age_restricted_denoms",
hash_context_restricted,
true }
};
for (size_t s = 0; s < sizeof(hive) / sizeof(hive[0]); s++)
@ -873,6 +885,8 @@ decode_keys_json (const json_t *resp_obj,
struct TALER_EXCHANGE_DenomPublicKey dk;
bool found = false;
have_age_restricted_denom = true;
memset (&dk,
0,
sizeof (dk));
@ -881,14 +895,15 @@ decode_keys_json (const json_t *resp_obj,
check_sig,
denom_key_obj,
&key_data->master_pub,
hash_context));
hive[s].hc));
/* Mark age restriction according where we got this denomination from,
* "denoms" or "age_restricted_denoms" */
if (hive[s].is_optional_age_restriction)
{
dk.age_restricted = true;
dk.age_mask.mask = key_data->age_mask.mask;
// dk.age_restricted = true;
// dk.age_mask.mask = key_data->age_mask.mask;
GNUNET_assert (0 != key_data->age_mask.mask);
}
for (unsigned int j = 0;
@ -1048,6 +1063,18 @@ decode_keys_json (const json_t *resp_obj,
.list_issue_date = GNUNET_TIME_timestamp_hton (key_data->list_issue_date)
};
/* If we had any age restricted denominations, add their hash to the end of
* the normal denominations. */
if (have_age_restricted_denom)
{
struct GNUNET_HashCode hcr;
GNUNET_CRYPTO_hash_context_finish (hash_context_restricted,
&hcr);
GNUNET_CRYPTO_hash_context_read (hash_context,
&hcr,
sizeof(struct GNUNET_HashCode));
}
GNUNET_CRYPTO_hash_context_finish (hash_context,
&ks.hc);
hash_context = NULL;

View File

@ -32,7 +32,7 @@
/**
* Set to 1 for extra debug logging.
*/
#define DEBUG 0
#define DEBUG 1 /* FIXME-oec */
/**

View File

@ -355,6 +355,7 @@ TALER_EXCHANGE_refresh_prepare (
struct MeltData md;
json_t *ret;
struct TALER_Amount total;
struct TALER_AgeCommitmentHash ach = {0};
struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA];
struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA];
@ -372,6 +373,7 @@ TALER_EXCHANGE_refresh_prepare (
md.melted_coin.original_value = melt_pk->value;
md.melted_coin.expire_deposit
= melt_pk->expire_deposit;
md.melted_coin.h_age_commitment = ach;
TALER_age_commitment_hash (age_commitment,
&md.melted_coin.h_age_commitment);

View File

@ -184,6 +184,7 @@ TALER_EXCHANGE_withdraw (
{
struct TALER_PlanchetDetail pd;
struct TALER_EXCHANGE_WithdrawHandle *wh;
bool age_restricted = (0 != pk->key.age_mask.mask);
wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
wh->exchange = exchange;
@ -193,8 +194,8 @@ TALER_EXCHANGE_withdraw (
wh->ps = *ps;
wh->ach = ach;
GNUNET_assert ( (pk->age_restricted && (NULL != ach)) ||
(! pk->age_restricted && (NULL == ach)) );
GNUNET_assert ( (age_restricted && (NULL != ach)) ||
(! age_restricted && (NULL == ach)));
if (GNUNET_OK !=
TALER_planchet_prepare (&pk->key,

View File

@ -209,6 +209,7 @@ test_exchange_api_LDADD = \
-lgnunetcurl \
-lgnunetutil \
-ljansson \
-ltalerextensions \
$(XLIB)
test_exchange_management_api_SOURCES = \

View File

@ -33,6 +33,7 @@
#include "taler_bank_service.h"
#include "taler_fakebank_lib.h"
#include "taler_testing_lib.h"
#include "taler_extensions.h"
/**
* Configuration file we use. One (big) configuration is used
@ -983,12 +984,12 @@ run (void *cls,
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_exec_offline_sign_extensions ("offline-sign-extensions",
CONFIG_FILE),
TALER_TESTING_cmd_wire_add ("add-wire-account",
"payto://x-taler-bank/localhost/2",
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_exec_offline_sign_extensions ("offline-sign-extensions",
CONFIG_FILE),
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
CONFIG_FILE),
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
@ -1042,6 +1043,9 @@ main (int argc,
GNUNET_log_setup ("test-exchange-api",
"INFO",
NULL);
TALER_extensions_init ();
/* Check fakebank port is available and get config */
if (GNUNET_OK !=
TALER_TESTING_prepare_fakebank (CONFIG_FILE,

View File

@ -997,6 +997,7 @@ melt_run (void *cls,
const struct TALER_DenominationSignature *melt_sig;
const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
const struct TALER_TESTING_Command *coin_command;
bool age_restricted;
if (NULL == (coin_command
= TALER_TESTING_interpreter_lookup_command
@ -1026,6 +1027,7 @@ melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_pub (coin_command,
0,
@ -1035,9 +1037,11 @@ melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is);
return;
}
/* Melt amount starts with the melt fee of the old coin; we'll add the
values and withdraw fees of the fresh coins next */
melt_amount = melt_denom_pub->fee_refresh;
age_restricted = melt_denom_pub->key.age_mask.mask != 0;
for (unsigned int i = 0; i<num_fresh_coins; i++)
{
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
@ -1055,7 +1059,7 @@ melt_run (void *cls,
}
fresh_pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (is->exchange),
&fresh_amount,
melt_denom_pub->age_restricted);
age_restricted);
if (NULL == fresh_pk)
{
GNUNET_break (0);
@ -1080,8 +1084,7 @@ melt_run (void *cls,
{
struct TALER_AgeCommitment *ac = NULL;
GNUNET_assert (melt_denom_pub->age_restricted ==
(NULL != rms->age_commitment));
GNUNET_assert (age_restricted == (NULL != rms->age_commitment));
if (NULL != rms->age_commitment)
{

View File

@ -464,12 +464,14 @@ withdraw_run (void *cls,
GNUNET_assert (GNUNET_OK ==
TALER_age_restriction_commit (
&ws->pk->age_mask,
&ws->pk->key.age_mask,
ws->age,
seed,
ac));
ws->age_commitment = ac;
ws->h_age_commitment = GNUNET_malloc (sizeof(struct
TALER_AgeCommitmentHash));
TALER_age_commitment_hash (
ac,
ws->h_age_commitment);

View File

@ -27,6 +27,7 @@
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_signatures.h"
#include "taler_extensions.h"
#include "taler_testing_lib.h"
/**
@ -440,7 +441,7 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
(GNUNET_TIME_timestamp_cmp (now,
<,
pk->withdraw_valid_until)) &&
(age_restricted == pk->age_restricted) )
(age_restricted == (0 != pk->key.age_mask.mask)) )
return pk;
}
/* do 2nd pass to check if expiration times are to blame for
@ -457,7 +458,7 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
GNUNET_TIME_timestamp_cmp (now,
>,
pk->withdraw_valid_until) ) &&
(age_restricted == pk->age_restricted) )
(age_restricted == (0 != pk->key.age_mask.mask)) )
{
GNUNET_log
(GNUNET_ERROR_TYPE_WARNING,