fix alignment issue, ensure we hash over packed structure to avoid non-determinism
This commit is contained in:
parent
66f9a5b5e5
commit
6a483b51ec
@ -2110,8 +2110,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
{
|
{
|
||||||
struct TEH_DenominationKey *dk;
|
struct TEH_DenominationKey *dk;
|
||||||
struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
|
struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
|
||||||
/* groupData is the value we store for each group meta-data */
|
/* GroupData is the value we store for each group meta-data */
|
||||||
struct groupData
|
struct GroupData
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The json blob with the group meta-data and list of denominations
|
* The json blob with the group meta-data and list of denominations
|
||||||
@ -2215,7 +2215,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
static const char *denoms_key = "denoms";
|
static const char *denoms_key = "denoms";
|
||||||
struct groupData *group;
|
struct GroupData *group;
|
||||||
json_t *list;
|
json_t *list;
|
||||||
json_t *entry;
|
json_t *entry;
|
||||||
struct GNUNET_HashCode key;
|
struct GNUNET_HashCode key;
|
||||||
@ -2226,28 +2226,19 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
.age_mask = dk->meta.age_mask,
|
.age_mask = dk->meta.age_mask,
|
||||||
};
|
};
|
||||||
|
|
||||||
memset (&meta.hash,
|
|
||||||
0,
|
|
||||||
sizeof(meta.hash));
|
|
||||||
/* Search the group/JSON-blob for the key */
|
/* Search the group/JSON-blob for the key */
|
||||||
GNUNET_CRYPTO_hash (&meta,
|
TALER_denomination_group_get_key (&meta,
|
||||||
sizeof(meta),
|
&key);
|
||||||
&key);
|
group = GNUNET_CONTAINER_multihashmap_get (
|
||||||
|
denominations_by_group,
|
||||||
group =
|
&key);
|
||||||
(struct groupData *) GNUNET_CONTAINER_multihashmap_get (
|
|
||||||
denominations_by_group,
|
|
||||||
&key);
|
|
||||||
|
|
||||||
if (NULL == group)
|
if (NULL == group)
|
||||||
{
|
{
|
||||||
/* There is no group for this meta-data yet, so we create a new group */
|
/* There is no group for this meta-data yet, so we create a new group */
|
||||||
bool age_restricted = meta.age_mask.bits != 0;
|
bool age_restricted = meta.age_mask.bits != 0;
|
||||||
const char *cipher;
|
const char *cipher;
|
||||||
|
|
||||||
group = GNUNET_new (struct groupData);
|
group = GNUNET_new (struct GroupData);
|
||||||
memset (group, 0, sizeof(*group));
|
|
||||||
|
|
||||||
switch (meta.cipher)
|
switch (meta.cipher)
|
||||||
{
|
{
|
||||||
case TALER_DENOMINATION_RSA:
|
case TALER_DENOMINATION_RSA:
|
||||||
@ -2261,9 +2252,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
group->json = GNUNET_JSON_PACK (
|
group->json = GNUNET_JSON_PACK (
|
||||||
GNUNET_JSON_pack_string ("cipher", cipher),
|
GNUNET_JSON_pack_string ("cipher",
|
||||||
TALER_JSON_PACK_DENOM_FEES ("fee", &meta.fees),
|
cipher),
|
||||||
TALER_JSON_pack_amount ("value", &meta.value));
|
TALER_JSON_PACK_DENOM_FEES ("fee",
|
||||||
|
&meta.fees),
|
||||||
|
TALER_JSON_pack_amount ("value",
|
||||||
|
&meta.value));
|
||||||
GNUNET_assert (NULL != group->json);
|
GNUNET_assert (NULL != group->json);
|
||||||
|
|
||||||
if (age_restricted)
|
if (age_restricted)
|
||||||
@ -2354,7 +2348,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
|
GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
|
||||||
{
|
{
|
||||||
struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
|
struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
|
||||||
struct groupData *group = NULL;
|
struct GroupData *group = NULL;
|
||||||
|
|
||||||
iter =
|
iter =
|
||||||
GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
|
GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
|
||||||
|
@ -6032,4 +6032,56 @@ TALER_age_restriction_from_secret (
|
|||||||
struct TALER_AgeCommitmentProof *comm_proof);
|
struct TALER_AgeCommitmentProof *comm_proof);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group of Denominations. These are the common fields of an array of
|
||||||
|
* denominations.
|
||||||
|
*
|
||||||
|
* The corresponding JSON-blob will also contain an array of particular
|
||||||
|
* denominations with only the timestamps, cipher-specific public key and the
|
||||||
|
* master signature.
|
||||||
|
*/
|
||||||
|
struct TALER_DenominationGroup
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XOR of all SHA-512 hashes of the public keys in this
|
||||||
|
* group.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of coins in this denomination group.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fee structure for all coins in the group.
|
||||||
|
*/
|
||||||
|
struct TALER_DenomFeeSet fees;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cipher used for the denomination.
|
||||||
|
*/
|
||||||
|
enum TALER_DenominationCipher cipher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Age mask for the denomiation.
|
||||||
|
*/
|
||||||
|
struct TALER_AgeMask age_mask;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a unique key for the meta data of a denomination group.
|
||||||
|
*
|
||||||
|
* @param dg denomination group to evaluate
|
||||||
|
* @param[out] key key to set
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_denomination_group_get_key (
|
||||||
|
const struct TALER_DenominationGroup *dg,
|
||||||
|
struct GNUNET_HashCode *key);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -380,26 +380,6 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
|
|||||||
TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \
|
TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \
|
||||||
TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse)
|
TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse)
|
||||||
|
|
||||||
/**
|
|
||||||
* Group of Denominations. These are the common fields of an array of
|
|
||||||
* denominations.
|
|
||||||
*
|
|
||||||
* The corresponding JSON-blob will also contain an array of particular
|
|
||||||
* denominations with only the timestamps, cipher-specific public key and the
|
|
||||||
* master signature.
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
struct TALER_DenominationGroup
|
|
||||||
{
|
|
||||||
enum TALER_DenominationCipher cipher;
|
|
||||||
struct TALER_Amount value;
|
|
||||||
struct TALER_DenomFeeSet fees;
|
|
||||||
struct TALER_AgeMask age_mask;
|
|
||||||
|
|
||||||
// hash is/should be the XOR of all SHA-512 hashes of the public keys in this
|
|
||||||
// group
|
|
||||||
struct GNUNET_HashCode hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a parser for a group of denominations.
|
* Generate a parser for a group of denominations.
|
||||||
|
@ -763,7 +763,7 @@ decode_keys_json (const json_t *resp_obj,
|
|||||||
key_data->age_mask = TALER_extensions_get_age_restriction_mask ();
|
key_data->age_mask = TALER_extensions_get_age_restriction_mask ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Parse the denomination keys, merging with the
|
* Parse the denomination keys, merging with the
|
||||||
* possibly EXISTING array as required (/keys cherry picking).
|
* possibly EXISTING array as required (/keys cherry picking).
|
||||||
*
|
*
|
||||||
@ -793,6 +793,9 @@ decode_keys_json (const json_t *resp_obj,
|
|||||||
&denom_keys_array),
|
&denom_keys_array),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
json_t *denom_key_obj;
|
||||||
|
unsigned int index;
|
||||||
|
|
||||||
EXITIF (GNUNET_SYSERR ==
|
EXITIF (GNUNET_SYSERR ==
|
||||||
GNUNET_JSON_parse (group_obj,
|
GNUNET_JSON_parse (group_obj,
|
||||||
group_spec,
|
group_spec,
|
||||||
@ -800,78 +803,73 @@ decode_keys_json (const json_t *resp_obj,
|
|||||||
NULL));
|
NULL));
|
||||||
|
|
||||||
/* Now, parse the individual denominations */
|
/* Now, parse the individual denominations */
|
||||||
|
json_array_foreach (denom_keys_array, index, denom_key_obj)
|
||||||
{
|
{
|
||||||
json_t *denom_key_obj;
|
/* Set the common fields from the group for this particular
|
||||||
unsigned int index;
|
denomination. Required to make the validity check inside
|
||||||
|
parse_json_denomkey_partially pass */
|
||||||
|
struct TALER_EXCHANGE_DenomPublicKey dk = {
|
||||||
|
.key.cipher = group.cipher,
|
||||||
|
.value = group.value,
|
||||||
|
.fees = group.fees,
|
||||||
|
.key.age_mask = group.age_mask
|
||||||
|
};
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
json_array_foreach (denom_keys_array, index, denom_key_obj)
|
EXITIF (GNUNET_SYSERR ==
|
||||||
|
parse_json_denomkey_partially (&dk,
|
||||||
|
group.cipher,
|
||||||
|
check_sig,
|
||||||
|
denom_key_obj,
|
||||||
|
&key_data->master_pub,
|
||||||
|
check_sig ? &hash_xor : NULL));
|
||||||
|
|
||||||
|
/* Build the running xor of the SHA512-hash of the public keys for the group */
|
||||||
|
GNUNET_CRYPTO_hash_xor (&dk.h_key.hash,
|
||||||
|
&group_hash_xor,
|
||||||
|
&group_hash_xor);
|
||||||
|
for (unsigned int j = 0;
|
||||||
|
j<key_data->num_denom_keys;
|
||||||
|
j++)
|
||||||
{
|
{
|
||||||
/* Set the common fields from the group for this particular
|
if (0 == denoms_cmp (&dk,
|
||||||
denomination. Required to make the validity check inside
|
&key_data->denom_keys[j]))
|
||||||
parse_json_denomkey_partially pass */
|
|
||||||
struct TALER_EXCHANGE_DenomPublicKey dk = {
|
|
||||||
.key.cipher = group.cipher,
|
|
||||||
.value = group.value,
|
|
||||||
.fees = group.fees,
|
|
||||||
.key.age_mask = group.age_mask
|
|
||||||
};
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
EXITIF (GNUNET_SYSERR ==
|
|
||||||
parse_json_denomkey_partially (&dk,
|
|
||||||
group.cipher,
|
|
||||||
check_sig,
|
|
||||||
denom_key_obj,
|
|
||||||
&key_data->master_pub,
|
|
||||||
check_sig ? &hash_xor : NULL));
|
|
||||||
|
|
||||||
/* Build the running xor of the SHA512-hash of the public keys for the group */
|
|
||||||
GNUNET_CRYPTO_hash_xor (&dk.h_key.hash,
|
|
||||||
&group_hash_xor,
|
|
||||||
&group_hash_xor);
|
|
||||||
for (unsigned int j = 0;
|
|
||||||
j<key_data->num_denom_keys;
|
|
||||||
j++)
|
|
||||||
{
|
{
|
||||||
if (0 == denoms_cmp (&dk,
|
found = true;
|
||||||
&key_data->denom_keys[j]))
|
break;
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
/* 0:0:0 did not support /keys cherry picking */
|
/* 0:0:0 did not support /keys cherry picking */
|
||||||
TALER_LOG_DEBUG ("Skipping denomination key: already know it\n");
|
TALER_LOG_DEBUG ("Skipping denomination key: already know it\n");
|
||||||
TALER_denom_pub_free (&dk.key);
|
TALER_denom_pub_free (&dk.key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_data->denom_keys_size == key_data->num_denom_keys)
|
if (key_data->denom_keys_size == key_data->num_denom_keys)
|
||||||
GNUNET_array_grow (key_data->denom_keys,
|
GNUNET_array_grow (key_data->denom_keys,
|
||||||
key_data->denom_keys_size,
|
key_data->denom_keys_size,
|
||||||
key_data->denom_keys_size * 2 + 2);
|
key_data->denom_keys_size * 2 + 2);
|
||||||
key_data->denom_keys[key_data->num_denom_keys++] = dk;
|
key_data->denom_keys[key_data->num_denom_keys++] = dk;
|
||||||
|
|
||||||
/* Update "last_denom_issue_date" */
|
/* Update "last_denom_issue_date" */
|
||||||
TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n",
|
TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n",
|
||||||
GNUNET_TIME_timestamp2s (dk.valid_from));
|
GNUNET_TIME_timestamp2s (dk.valid_from));
|
||||||
key_data->last_denom_issue_date
|
key_data->last_denom_issue_date
|
||||||
= GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date,
|
= GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date,
|
||||||
dk.valid_from);
|
dk.valid_from);
|
||||||
}; /* end of json_array_foreach over denominations */
|
}; /* end of json_array_foreach over denominations */
|
||||||
|
|
||||||
/* The calculated group_hash_xor must be the same as group.hash from
|
/* The calculated group_hash_xor must be the same as group.hash from
|
||||||
the JSON. */
|
the JSON. */
|
||||||
EXITIF (0 !=
|
EXITIF (0 !=
|
||||||
GNUNET_CRYPTO_hash_cmp (&group_hash_xor,
|
GNUNET_CRYPTO_hash_cmp (&group_hash_xor,
|
||||||
&group.hash));
|
&group.hash));
|
||||||
|
|
||||||
} /* end of block for parsing individual denominations */
|
|
||||||
} /* end of json_array_foreach over groups of denominations */
|
} /* end of json_array_foreach over groups of denominations */
|
||||||
}
|
} /* end of scope for group_ojb/group_idx */
|
||||||
|
|
||||||
/* parse the auditor information */
|
/* parse the auditor information */
|
||||||
{
|
{
|
||||||
@ -1620,11 +1618,6 @@ struct GroupData
|
|||||||
*/
|
*/
|
||||||
json_t *json;
|
json_t *json;
|
||||||
|
|
||||||
/**
|
|
||||||
* xor of all hashes of denominations in that group
|
|
||||||
*/
|
|
||||||
struct GNUNET_HashCode hash_xor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meta data for this group.
|
* Meta data for this group.
|
||||||
*/
|
*/
|
||||||
@ -1668,7 +1661,7 @@ add_grp (void *cls,
|
|||||||
|
|
||||||
ge = GNUNET_JSON_PACK (
|
ge = GNUNET_JSON_PACK (
|
||||||
GNUNET_JSON_pack_data_auto ("hash",
|
GNUNET_JSON_pack_data_auto ("hash",
|
||||||
&gd->hash_xor),
|
&gd->meta.hash),
|
||||||
GNUNET_JSON_pack_string ("cipher",
|
GNUNET_JSON_pack_string ("cipher",
|
||||||
cipher),
|
cipher),
|
||||||
GNUNET_JSON_pack_array_steal ("denoms",
|
GNUNET_JSON_pack_array_steal ("denoms",
|
||||||
@ -1751,8 +1744,7 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
|
|||||||
json_decref (signkeys);
|
json_decref (signkeys);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// FIXME: construct denominations_by_group analogous
|
|
||||||
// to taler-exchange-httpd_keys!
|
|
||||||
{
|
{
|
||||||
struct GNUNET_CONTAINER_MultiHashMap *dbg;
|
struct GNUNET_CONTAINER_MultiHashMap *dbg;
|
||||||
|
|
||||||
@ -1776,9 +1768,8 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
|
|||||||
>,
|
>,
|
||||||
dk->expire_deposit))
|
dk->expire_deposit))
|
||||||
continue; /* skip keys that have expired */
|
continue; /* skip keys that have expired */
|
||||||
GNUNET_CRYPTO_hash (&meta,
|
TALER_denomination_group_get_key (&meta,
|
||||||
sizeof(meta),
|
&key);
|
||||||
&key);
|
|
||||||
gd = GNUNET_CONTAINER_multihashmap_get (dbg,
|
gd = GNUNET_CONTAINER_multihashmap_get (dbg,
|
||||||
&key);
|
&key);
|
||||||
if (NULL == gd)
|
if (NULL == gd)
|
||||||
@ -1794,18 +1785,11 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
|
|||||||
gd,
|
gd,
|
||||||
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
|
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
|
||||||
|
|
||||||
/* Build the running xor of the SHA512-hash of the public keys */
|
|
||||||
}
|
}
|
||||||
{
|
/* Build the running xor of the SHA512-hash of the public keys */
|
||||||
struct TALER_DenominationHashP hc;
|
GNUNET_CRYPTO_hash_xor (&dk->h_key.hash,
|
||||||
|
&gd->meta.hash,
|
||||||
TALER_denom_pub_hash (&dk->key,
|
&gd->meta.hash);
|
||||||
&hc);
|
|
||||||
GNUNET_CRYPTO_hash_xor (&hc.hash,
|
|
||||||
&gd->hash_xor,
|
|
||||||
&gd->hash_xor);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (meta.cipher)
|
switch (meta.cipher)
|
||||||
{
|
{
|
||||||
case TALER_DENOMINATION_RSA:
|
case TALER_DENOMINATION_RSA:
|
||||||
@ -1833,10 +1817,6 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd)
|
|||||||
dk->valid_from),
|
dk->valid_from),
|
||||||
GNUNET_JSON_pack_timestamp ("stamp_expire_legal",
|
GNUNET_JSON_pack_timestamp ("stamp_expire_legal",
|
||||||
dk->expire_legal),
|
dk->expire_legal),
|
||||||
TALER_JSON_pack_amount ("value",
|
|
||||||
&dk->value),
|
|
||||||
TALER_JSON_PACK_DENOM_FEES ("fee",
|
|
||||||
&dk->fees),
|
|
||||||
GNUNET_JSON_pack_data_auto ("master_sig",
|
GNUNET_JSON_pack_data_auto ("master_sig",
|
||||||
&dk->master_sig),
|
&dk->master_sig),
|
||||||
key_spec
|
key_spec
|
||||||
|
@ -461,4 +461,54 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_BEGIN
|
||||||
|
/**
|
||||||
|
* Structure we hash to compute the group key for
|
||||||
|
* a denomination group.
|
||||||
|
*/
|
||||||
|
struct DenominationGroupP
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Value of coins in this denomination group.
|
||||||
|
*/
|
||||||
|
struct TALER_AmountNBO value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fee structure for all coins in the group.
|
||||||
|
*/
|
||||||
|
struct TALER_DenomFeeSetNBOP fees;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Age mask for the denomiation, in NBO.
|
||||||
|
*/
|
||||||
|
uint32_t age_mask GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cipher used for the denomination, in NBO.
|
||||||
|
*/
|
||||||
|
uint32_t cipher GNUNET_PACKED;
|
||||||
|
};
|
||||||
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TALER_denomination_group_get_key (
|
||||||
|
const struct TALER_DenominationGroup *dg,
|
||||||
|
struct GNUNET_HashCode *key)
|
||||||
|
{
|
||||||
|
struct DenominationGroupP dgp = {
|
||||||
|
.age_mask = htonl (dg->age_mask.bits),
|
||||||
|
.cipher = htonl (dg->cipher)
|
||||||
|
};
|
||||||
|
|
||||||
|
TALER_amount_hton (&dgp.value,
|
||||||
|
&dg->value);
|
||||||
|
TALER_denom_fee_set_hton (&dgp.fees,
|
||||||
|
&dg->fees);
|
||||||
|
GNUNET_CRYPTO_hash (&dgp,
|
||||||
|
sizeof (dgp),
|
||||||
|
key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of crypto.c */
|
/* end of crypto.c */
|
||||||
|
Loading…
Reference in New Issue
Block a user