summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2022-06-27 10:10:51 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2022-06-27 10:10:51 +0200
commita6544069f98fdbfce4ac215dd5f0ee0660469c2c (patch)
treed076bdb636acca8fb5f587c0971ed176cf1776f3
parenta55fc45126b13de56a76a44f629a73b1eb003408 (diff)
downloadexchange-a6544069f98fdbfce4ac215dd5f0ee0660469c2c.tar.gz
exchange-a6544069f98fdbfce4ac215dd5f0ee0660469c2c.tar.bz2
exchange-a6544069f98fdbfce4ac215dd5f0ee0660469c2c.zip
[new /keys response] added proper hash verification
- Running XOR of all SHA-512 hashes of each denomination's public key is compared against the "hash" value in the JSON blob. - Fixed a bug during creation of the running XOR.
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c36
-rw-r--r--src/include/taler_json_lib.h9
-rw-r--r--src/json/json_helper.c2
-rw-r--r--src/lib/exchange_api_handle.c52
4 files changed, 66 insertions, 33 deletions
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index de5f1fbc..ee80dcf9 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -2068,24 +2068,27 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
last_cpd = GNUNET_TIME_UNIT_ZERO_TS;
+ // FIXME: This block contains the implementation of the DEPRICATED
+ // "denom_pubs" array along with the new grouped "denominations".
+ // "denom_pubs" Will be removed sooner or later.
{
struct TEH_DenominationKey *dk;
struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
-
- denominations_by_group =
- GNUNET_CONTAINER_multihashmap_create (1024,
- GNUNET_NO /* NO, because keys are only on the stack */);
-
- /* groupData is the value we store for each group meta-data */
+ // groupData is the value we store for each group meta-data
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
json_t *json;
- /* xor of all hashes of denominations in that group */
+ // xor of all hashes of denominations in that group
struct GNUNET_HashCode hash_xor;
};
+ denominations_by_group =
+ GNUNET_CONTAINER_multihashmap_create (1024,
+ GNUNET_NO /* NO, because keys are only on the stack */);
+
+
/* heap = min heap, sorted by start time */
while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap)))
{
@@ -2113,7 +2116,6 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
recoup,
denoms,
grouped_denominations,
-
&grouped_hash_xor))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -2318,24 +2320,26 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
(const
void **) &group))
{
- struct GNUNET_HashCode hc;
-
- GNUNET_CRYPTO_hash_xor (&group->hash_xor,
- &grouped_hash_xor,
- &grouped_hash_xor);
-
+ // Add the XOR over all hashes of denominations in this group to the group
GNUNET_assert (0 ==
json_object_set (
group->json,
"hash",
GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto (NULL, &hc))));
+ GNUNET_JSON_pack_data_auto (NULL,
+ &group->hash_xor))));
+ // Add this group to the array
GNUNET_assert (0 ==
json_array_append_new (
grouped_denominations,
group->json));
+ // Build the running XOR over all hash(_xor)
+ GNUNET_CRYPTO_hash_xor (&group->hash_xor,
+ &grouped_hash_xor,
+ &grouped_hash_xor);
+
GNUNET_free (group);
}
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index f0b105e9..0b58b43d 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -370,12 +370,17 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
**/
struct TALER_DenominationGroup
{
- /* currency must be set prior to calling TALER_JSON_spec_denomination_group */
- const char *currency;
enum TALER_DenominationCipher cipher;
struct TALER_Amount value;
struct TALER_DenomFeeSet fees;
struct TALER_AgeMask age_mask;
+
+ // currency must be set prior to calling TALER_JSON_spec_denomination_group
+ const char *currency;
+
+ // hash is/should be the XOR of all SHA-512 hashes of the public keys in this
+ // group
+ struct GNUNET_HashCode hash;
};
/**
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 9752bb9f..b29a49b3 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -265,6 +265,8 @@ parse_denomination_group (void *cls,
GNUNET_JSON_spec_uint32 ("age_mask",
&group->age_mask.bits),
&age_mask_missing),
+ GNUNET_JSON_spec_fixed_auto ("hash",
+ &group->hash),
GNUNET_JSON_spec_end ()
};
const char *emsg;
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index be7bb3c3..c690c352 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -924,8 +924,13 @@ decode_keys_json (const json_t *resp_obj,
key_data->age_mask = TALER_extensions_age_restriction_ageMask ();
}
- /* parse the denomination keys, merging with the
- possibly EXISTING array as required (/keys cherry picking) */
+ /**
+ * Parse the denomination keys, merging with the
+ * possibly EXISTING array as required (/keys cherry picking).
+ *
+ * The denominations are grouped by common values of
+ * {cipher, value, fee, age_mask}.
+ **/
{
json_t *denominations_by_group;
json_t *group_obj;
@@ -940,23 +945,25 @@ decode_keys_json (const json_t *resp_obj,
json_typeof (denominations_by_group));
json_array_foreach (denominations_by_group, group_idx, group_obj) {
- /* First, parse { cipher, fees, value, age_mask } of the current group */
-
- struct TALER_DenominationGroup group = {
- .currency = currency
- };
+ // Running XOR of each SHA512 hash of the denominations' public key in
+ // this group. Used to compare against group.hash after all keys have
+ // been parsed.
+ struct GNUNET_HashCode group_hash_xor = {0};
+
+ // First, parse { cipher, fees, value, age_mask, hash } of the current
+ // group.
+ struct TALER_DenominationGroup group = { .currency = currency };
struct GNUNET_JSON_Specification group_spec[] = {
TALER_JSON_spec_denomination_group (NULL, &group),
GNUNET_JSON_spec_end ()
};
-
EXITIF (GNUNET_SYSERR ==
GNUNET_JSON_parse (group_obj,
group_spec,
NULL,
NULL));
- /* Now, parse the individual denominations */
+ // Now, parse the individual denominations
{
json_t *denom_keys_array;
json_t *denom_key_obj;
@@ -970,9 +977,9 @@ decode_keys_json (const json_t *resp_obj,
memset (&dk, 0, sizeof (dk));
- /* Set the common fields from the group for this particular
- * denomination. Required to make the validity check inside
- * parse_json_denomkey_partially pass */
+ // Set the common fields from the group for this particular
+ // denomination. Required to make the validity check inside
+ // parse_json_denomkey_partially pass
dk.key.cipher = group.cipher;
dk.value = group.value;
dk.fees = group.fees;
@@ -987,6 +994,15 @@ decode_keys_json (const json_t *resp_obj,
&key_data->master_pub,
check_sig ? &hash_xor: NULL));
+ // Build the running xor of the SHA512-hash of the public keys
+ {
+ struct TALER_DenominationHashP hc = {0};
+ TALER_denom_pub_hash (&dk.key, &hc);
+ GNUNET_CRYPTO_hash_xor (&hc.hash,
+ &group_hash_xor,
+ &group_hash_xor);
+ }
+
for (unsigned int j = 0;
j<key_data->num_denom_keys;
j++)
@@ -1019,9 +1035,15 @@ decode_keys_json (const json_t *resp_obj,
key_data->last_denom_issue_date
= GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date,
dk.valid_from);
- }
- };
- };
+ }; // json_array_foreach over denominations
+
+ // The calculated group_hash_xor must be the same as group.hash from
+ // the json.
+ EXITIF (0 !=
+ GNUNET_CRYPTO_hash_cmp (&group_hash_xor, &group.hash));
+
+ } // block for parsing individual denominations
+ }; // json_array_foreach over groups of denominations
}
/* parse the auditor information */