aboutsummaryrefslogtreecommitdiff
path: root/src/json
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2022-06-26 16:59:27 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2022-06-26 16:59:27 +0200
commit31f74059e0d710254397688aabc201b230ef27da (patch)
tree8a9717ae3d729c5916db15c7407d8d68b2828f85 /src/json
parentb39febe36fd66c8a36469cbedbc6197cc6c60135 (diff)
[new /keys response] create and parse denomination implemented
- /keys response now contains signed denomintations - hashes of denominations now XOR'ed per group into a single hash-code - final hash-code is now XOR of all group hash codes - final hash-code is signed - lib/exchange_api_handle support for new "denominations" implemented - parses array of denomation groups - creates running xor of hashes - verifies signature at the end - previous diff/merge logic for keys remains intact.
Diffstat (limited to 'src/json')
-rw-r--r--src/json/json_helper.c188
-rw-r--r--src/json/json_pack.c23
2 files changed, 195 insertions, 16 deletions
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 11aeceefb..9752bb9f8 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -35,11 +35,15 @@
static enum TALER_DenominationCipher
string_to_cipher (const char *cipher_s)
{
- if (0 == strcasecmp (cipher_s,
- "RSA"))
+ if ((0 == strcasecmp (cipher_s,
+ "RSA")) ||
+ (0 == strcasecmp (cipher_s,
+ "RSA+age_restricted")))
return TALER_DENOMINATION_RSA;
- if (0 == strcasecmp (cipher_s,
- "CS"))
+ if ((0 == strcasecmp (cipher_s,
+ "CS")) ||
+ (0 == strcasecmp (cipher_s,
+ "CS+age_restricted")))
return TALER_DENOMINATION_CS;
return TALER_DENOMINATION_INVALID;
}
@@ -239,6 +243,84 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
}
+static enum GNUNET_GenericReturnValue
+parse_denomination_group (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct TALER_DenominationGroup *group = spec->ptr;
+ const char *cipher;
+ bool age_mask_missing = false;
+ bool has_age_restricted_suffix = false;
+ struct GNUNET_JSON_Specification gspec[] = {
+ GNUNET_JSON_spec_string ("cipher",
+ &cipher),
+ TALER_JSON_spec_amount ("value",
+ group->currency,
+ &group->value),
+ TALER_JSON_SPEC_DENOM_FEES ("fee",
+ group->currency,
+ &group->fees),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("age_mask",
+ &group->age_mask.bits),
+ &age_mask_missing),
+ GNUNET_JSON_spec_end ()
+ };
+ const char *emsg;
+ unsigned int eline;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (root,
+ gspec,
+ &emsg,
+ &eline))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ group->cipher = string_to_cipher (cipher);
+ if (TALER_DENOMINATION_INVALID == group->cipher)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ /* age_mask and suffix must be consistent */
+ has_age_restricted_suffix =
+ (NULL != strstr (cipher, "+age_restricted"));
+ if (has_age_restricted_suffix && age_mask_missing)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (age_mask_missing)
+ group->age_mask.bits = 0;
+
+ return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_denomination_group (const char *name,
+ struct TALER_DenominationGroup *group)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_denomination_group,
+ .cleaner = NULL,
+ .field = name,
+ .ptr = group,
+ .ptr_size = sizeof(*group),
+ .size_ptr = NULL,
+ };
+
+
+ return ret;
+}
+
+
/**
* Parse given JSON object to an encrypted contract.
*
@@ -330,11 +412,14 @@ parse_denom_pub (void *cls,
{
struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
const char *cipher;
+ bool age_mask_missing = false;
struct GNUNET_JSON_Specification dspec[] = {
GNUNET_JSON_spec_string ("cipher",
&cipher),
- GNUNET_JSON_spec_uint32 ("age_mask",
- &denom_pub->age_mask.bits),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("age_mask",
+ &denom_pub->age_mask.bits),
+ &age_mask_missing),
GNUNET_JSON_spec_end ()
};
const char *emsg;
@@ -350,6 +435,10 @@ parse_denom_pub (void *cls,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+
+ if (age_mask_missing)
+ denom_pub->age_mask.bits = 0;
+
denom_pub->cipher = string_to_cipher (cipher);
switch (denom_pub->cipher)
{
@@ -434,6 +523,93 @@ TALER_JSON_spec_denom_pub (const char *field,
/**
+ * Parse given JSON object partially into a denomination public key.
+ *
+ * Depending on the cipher in cls, it parses the corresponding public key type.
+ *
+ * @param cls closure, enum TALER_DenominationCipher
+ * @param cipher cipher to parse for
+ * @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_denom_pub_cipher (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
+ enum TALER_DenominationCipher cipher = (enum TALER_DenominationCipher) cls;
+ const char *emsg;
+ unsigned int eline;
+
+ switch (cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ {
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_rsa_public_key (
+ "rsa_pub",
+ &denom_pub->details.rsa_public_key),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (root,
+ ispec,
+ &emsg,
+ &eline))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+ }
+ case TALER_DENOMINATION_CS:
+ {
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_fixed ("cs_pub",
+ &denom_pub->details.cs_public_key,
+ sizeof (denom_pub->details.cs_public_key)),
+ 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;
+ }
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_denom_pub_cipher (const char *field,
+ enum TALER_DenominationCipher cipher,
+ struct TALER_DenominationPublicKey *pk)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_denom_pub_cipher,
+ .cleaner = &clean_denom_pub,
+ .field = field,
+ .cls = (void *) cipher,
+ .ptr = pk
+ };
+
+ return ret;
+}
+
+
+/**
* Parse given JSON object to denomination signature.
*
* @param cls closure, NULL
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index 090a8b96b..bb52eeb05 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -79,35 +79,38 @@ TALER_JSON_pack_denom_pub (
struct GNUNET_JSON_PackSpec ps = {
.field_name = name,
};
+ struct GNUNET_JSON_PackSpec mask_or_end;
if (NULL == pk)
return ps;
+
+ mask_or_end = (0 != pk->age_mask.bits) ?
+ GNUNET_JSON_pack_uint64 ("age_mask", pk->age_mask.bits) :
+ GNUNET_JSON_pack_end_ ();
+
switch (pk->cipher)
{
case TALER_DENOMINATION_RSA:
ps.object
= GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("cipher",
- "RSA"),
- GNUNET_JSON_pack_uint64 ("age_mask",
- pk->age_mask.bits),
+ GNUNET_JSON_pack_string ("cipher", "RSA"),
GNUNET_JSON_pack_rsa_public_key ("rsa_public_key",
- pk->details.rsa_public_key));
+ pk->details.rsa_public_key),
+ mask_or_end);
break;
case TALER_DENOMINATION_CS:
ps.object
= GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("cipher",
- "CS"),
- GNUNET_JSON_pack_uint64 ("age_mask",
- pk->age_mask.bits),
+ GNUNET_JSON_pack_string ("cipher", "CS"),
GNUNET_JSON_pack_data_varsize ("cs_public_key",
&pk->details.cs_public_key,
- sizeof (pk->details.cs_public_key)));
+ sizeof (pk->details.cs_public_key)),
+ mask_or_end);
break;
default:
GNUNET_assert (0);
}
+
return ps;
}