summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_mint_service.h32
-rw-r--r--src/include/taler_signatures.h72
-rw-r--r--src/mint-lib/mint_api_handle.c167
3 files changed, 258 insertions, 13 deletions
diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h
index 3f89b0745..8d569d4bc 100644
--- a/src/include/taler_mint_service.h
+++ b/src/include/taler_mint_service.h
@@ -150,6 +150,11 @@ struct TALER_MINT_DenomPublicKey
struct TALER_DenominationPublicKey key;
/**
+ * The hash of the public key.
+ */
+ struct GNUNET_HashCode h_key;
+
+ /**
* Timestamp indicating when the denomination key becomes valid
*/
struct GNUNET_TIME_Absolute valid_from;
@@ -166,6 +171,15 @@ struct TALER_MINT_DenomPublicKey
struct GNUNET_TIME_Absolute deposit_valid_until;
/**
+ * When do signatures with this denomination key become invalid?
+ * After this point, these signatures cannot be used in (legal)
+ * disputes anymore, as the Mint is then allowed to destroy its side
+ * of the evidence. @e expire_legal is expected to be significantly
+ * larger than @e expire_spend (by a year or more).
+ */
+ struct GNUNET_TIME_Absolute expire_legal;
+
+ /**
* The value of this denomination
*/
struct TALER_Amount value;
@@ -204,6 +218,8 @@ struct TALER_MINT_AuditorInformation
* that website. We expect that in practice software is going to
* often ship with an initial list of accepted auditors, just like
* browsers ship with a CA root store.
+ *
+ * This field may be NULL. (#3987).
*/
const char *auditor_url;
@@ -218,7 +234,7 @@ struct TALER_MINT_AuditorInformation
* elements point to the same locations as the entries
* in the key's main `denom_keys` array.
*/
- struct TALER_MINT_DenomPublicKey *const*denom_keys;
+ const struct TALER_MINT_DenomPublicKey **denom_keys;
};
@@ -246,7 +262,7 @@ struct TALER_MINT_Keys
/**
* Array of the keys of the auditors of the mint.
*/
- struct TALER_AuditorPublicKeyP *auditors;
+ struct TALER_MINT_AuditorInformation *auditors;
/**
* Length of the @e sign_keys array.
@@ -353,6 +369,18 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
const struct TALER_DenominationPublicKey *pk);
+/**
+ * Obtain the denomination key details from the mint.
+ *
+ * @param keys the mint's key set
+ * @param hc hash of the public key of the denomination to lookup
+ * @return details about the given denomination key
+ */
+const struct TALER_MINT_DenomPublicKey *
+TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
+ const struct GNUNET_HashCode *hc);
+
+
/* ********************* /wire *********************** */
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index ffbc9fd45..3bdc4eee1 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -653,13 +653,73 @@ struct TALER_MintKeyValidityPS
struct TALER_MasterPublicKeyP master;
/**
- * Array of hash(es) of the mint's denomination keys.
- * Specifically, this is the hash over the
- * `struct TALER_DenominationKeyValidityPS`, not just
- * the public key (as the auditor needs to check against
- * the correct valuations and fee structure).
+ * Start time of the validity period for this key.
+ */
+ struct GNUNET_TIME_AbsoluteNBO start;
+
+ /**
+ * The mint will sign fresh coins between @e start and this time.
+ * @e expire_withdraw will be somewhat larger than @e start to
+ * ensure a sufficiently large anonymity set, while also allowing
+ * the Mint to limit the financial damage in case of a key being
+ * compromised. Thus, mints with low volume are expected to have a
+ * longer withdraw period (@e expire_withdraw - @e start) than mints
+ * with high transaction volume. The period may also differ between
+ * types of coins. A mint may also have a few denomination keys
+ * with the same value with overlapping validity periods, to address
+ * issues such as clock skew.
+ */
+ struct GNUNET_TIME_AbsoluteNBO expire_withdraw;
+
+ /**
+ * Coins signed with the denomination key must be spent or refreshed
+ * between @e start and this expiration time. After this time, the
+ * mint will refuse transactions involving this key as it will
+ * "drop" the table with double-spending information (shortly after)
+ * this time. Note that wallets should refresh coins significantly
+ * before this time to be on the safe side. @e expire_spend must be
+ * significantly larger than @e expire_withdraw (by months or even
+ * years).
+ */
+ struct GNUNET_TIME_AbsoluteNBO expire_spend;
+
+ /**
+ * When do signatures with this denomination key become invalid?
+ * After this point, these signatures cannot be used in (legal)
+ * disputes anymore, as the Mint is then allowed to destroy its side
+ * of the evidence. @e expire_legal is expected to be significantly
+ * larger than @e expire_spend (by a year or more).
*/
- /* struct GNUNET_HashCode h_dks; */
+ struct GNUNET_TIME_AbsoluteNBO expire_legal;
+
+ /**
+ * The value of the coins signed with this denomination key.
+ */
+ struct TALER_AmountNBO value;
+
+ /**
+ * The fee the mint charges when a coin of this type is withdrawn.
+ * (can be zero).
+ */
+ struct TALER_AmountNBO fee_withdraw;
+
+ /**
+ * The fee the mint charges when a coin of this type is deposited.
+ * (can be zero).
+ */
+ struct TALER_AmountNBO fee_deposit;
+
+ /**
+ * The fee the mint charges when a coin of this type is refreshed.
+ * (can be zero).
+ */
+ struct TALER_AmountNBO fee_refresh;
+
+ /**
+ * Hash code of the denomination public key. (Used to avoid having
+ * the variable-size RSA key in this struct.)
+ */
+ struct GNUNET_HashCode denom_hash GNUNET_PACKED;
};
diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c
index f5e26ff15..9eaa6171d 100644
--- a/src/mint-lib/mint_api_handle.c
+++ b/src/mint-lib/mint_api_handle.c
@@ -325,9 +325,11 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
&denom_key_issue.denom_hash,
sizeof (struct GNUNET_HashCode));
denom_key->key.rsa_public_key = pk;
+ denom_key->h_key = denom_key_issue.denom_hash;
denom_key->valid_from = valid_from;
denom_key->withdraw_valid_until = withdraw_valid_until;
denom_key->deposit_valid_until = deposit_valid_until;
+ denom_key->expire_legal = expire_legal;
denom_key->value = value;
denom_key->fee_withdraw = fee_withdraw;
denom_key->fee_deposit = fee_deposit;
@@ -341,6 +343,116 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
/**
+ * Parse a mint's auditor information encoded in JSON.
+ *
+ * @param[out] auditor where to return the result
+ * @param[in] auditor_obj json to parse
+ * @param key_data information about denomination keys
+ * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
+ * invalid or the json malformed.
+ */
+static int
+parse_json_auditor (struct TALER_MINT_AuditorInformation *auditor,
+ json_t *auditor_obj,
+ const struct TALER_MINT_Keys *key_data)
+{
+ json_t *keys;
+ json_t *key;
+ unsigned int len;
+ unsigned int off;
+ unsigned int i;
+ struct TALER_MintKeyValidityPS kv;
+ struct MAJ_Specification spec[] = {
+ MAJ_spec_fixed_auto ("auditor_pub",
+ &auditor->auditor_pub),
+ MAJ_spec_json ("denomination_keys",
+ &keys),
+ MAJ_spec_end
+ };
+
+ auditor->auditor_url = NULL; /* #3987 */
+ if (GNUNET_OK !=
+ MAJ_parse_json (auditor_obj,
+ spec))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
+ kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
+ kv.master = key_data->master_pub;
+ len = json_array_size (keys);
+ auditor->denom_keys = GNUNET_new_array (len,
+ const struct TALER_MINT_DenomPublicKey *);
+ i = 0;
+ off = 0;
+ json_array_foreach (keys, i, key) {
+ struct TALER_AuditorSignatureP auditor_sig;
+ struct GNUNET_HashCode denom_h;
+ const struct TALER_MINT_DenomPublicKey *dk;
+ unsigned int j;
+ struct MAJ_Specification spec[] = {
+ MAJ_spec_fixed_auto ("denom_pub_h",
+ &denom_h),
+ MAJ_spec_fixed_auto ("auditor_sig",
+ &auditor_sig),
+ MAJ_spec_end
+ };
+
+ if (GNUNET_OK !=
+ MAJ_parse_json (key,
+ spec))
+ {
+ GNUNET_break_op (0);
+ continue;
+ }
+ dk = NULL;
+ for (j=0;j<key_data->num_denom_keys;j++)
+ {
+ if (0 == memcmp (&denom_h,
+ &key_data->denom_keys[j].h_key,
+ sizeof (struct GNUNET_HashCode)))
+ {
+ dk = &key_data->denom_keys[j];
+ break;
+ }
+ }
+ if (NULL == dk)
+ {
+ GNUNET_break_op (0);
+ continue;
+ }
+ kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
+ kv.expire_withdraw = GNUNET_TIME_absolute_hton (dk->withdraw_valid_until);
+ kv.expire_spend = GNUNET_TIME_absolute_hton (dk->deposit_valid_until);
+ kv.expire_legal = GNUNET_TIME_absolute_hton (dk->expire_legal);
+ TALER_amount_hton (&kv.value,
+ &dk->value);
+ TALER_amount_hton (&kv.fee_withdraw,
+ &dk->fee_withdraw);
+ TALER_amount_hton (&kv.fee_deposit,
+ &dk->fee_deposit);
+ TALER_amount_hton (&kv.fee_refresh,
+ &dk->fee_refresh);
+ kv.denom_hash = dk->h_key;
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_MINT_KEYS,
+ &kv.purpose,
+ &auditor_sig.eddsa_sig,
+ &auditor->auditor_pub.eddsa_pub))
+ {
+ GNUNET_break_op (0);
+ continue;
+ }
+ auditor->denom_keys[off] = dk;
+ off++;
+ }
+ auditor->num_denom_keys = off;
+ return GNUNET_OK;
+}
+
+
+/**
* Decode the JSON in @a resp_obj from the /keys response and store the data
* in the @a key_data.
*
@@ -394,8 +506,8 @@ decode_keys_json (json_t *resp_obj,
EXITIF (0 == (key_data->num_sign_keys =
json_array_size (sign_keys_array)));
key_data->sign_keys
- = GNUNET_malloc (sizeof (struct TALER_MINT_SigningPublicKey)
- * key_data->num_sign_keys);
+ = GNUNET_new_array (key_data->num_sign_keys,
+ struct TALER_MINT_SigningPublicKey);
index = 0;
json_array_foreach (sign_keys_array, index, sign_key_obj) {
EXITIF (GNUNET_SYSERR ==
@@ -415,8 +527,8 @@ decode_keys_json (json_t *resp_obj,
json_object_get (resp_obj, "denoms")));
EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
EXITIF (0 == (key_data->num_denom_keys = json_array_size (denom_keys_array)));
- key_data->denom_keys = GNUNET_malloc (sizeof (struct TALER_MINT_DenomPublicKey)
- * key_data->num_denom_keys);
+ key_data->denom_keys = GNUNET_new_array (key_data->num_denom_keys,
+ struct TALER_MINT_DenomPublicKey);
index = 0;
json_array_foreach (denom_keys_array, index, denom_key_obj) {
EXITIF (GNUNET_SYSERR ==
@@ -427,7 +539,30 @@ decode_keys_json (json_t *resp_obj,
}
}
- /* FIXME: parse the auditor keys (#3847) */
+ /* parse the auditor information */
+ {
+ json_t *auditors_array;
+ json_t *auditor_info;
+ unsigned int len;
+ unsigned int index;
+
+ EXITIF (NULL == (auditors_array =
+ json_object_get (resp_obj, "auditors")));
+ EXITIF (JSON_ARRAY != json_typeof (auditors_array));
+ len = json_array_size (auditors_array);
+ if (0 != len)
+ {
+ key_data->auditors = GNUNET_new_array (len,
+ struct TALER_MINT_AuditorInformation);
+ index = 0;
+ json_array_foreach (auditors_array, index, auditor_info) {
+ EXITIF (GNUNET_SYSERR ==
+ parse_json_auditor (&key_data->auditors[index],
+ auditor_info,
+ key_data));
+ }
+ }
+ }
/* Validate signature... */
ks.purpose.size = htonl (sizeof (ks));
@@ -709,6 +844,28 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
/**
+ * Obtain the denomination key details from the mint.
+ *
+ * @param keys the mint's key set
+ * @param hc hash of the public key of the denomination to lookup
+ * @return details about the given denomination key
+ */
+const struct TALER_MINT_DenomPublicKey *
+TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
+ const struct GNUNET_HashCode *hc)
+{
+ unsigned int i;
+
+ for (i=0;i<keys->num_denom_keys;i++)
+ if (0 == memcmp (hc,
+ &keys->denom_keys[i].h_key,
+ sizeof (struct GNUNET_HashCode)))
+ return &keys->denom_keys[i];
+ return NULL;
+}
+
+
+/**
* Obtain the keys from the mint.
*
* @param mint the mint handle