summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am1
-rw-r--r--src/lib/anastasis_backup.c113
-rw-r--r--src/lib/anastasis_meta.c178
-rw-r--r--src/lib/anastasis_recovery.c721
4 files changed, 652 insertions, 361 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 07460d4..6f71418 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -14,6 +14,7 @@ libanastasis_la_LDFLAGS = \
-no-undefined
libanastasis_la_SOURCES = \
anastasis_backup.c \
+ anastasis_meta.c \
anastasis_recovery.c
libanastasis_la_LIBADD = \
$(top_builddir)/src/util/libanastasisutil.la \
diff --git a/src/lib/anastasis_backup.c b/src/lib/anastasis_backup.c
index 6747d73..24d9643 100644
--- a/src/lib/anastasis_backup.c
+++ b/src/lib/anastasis_backup.c
@@ -3,14 +3,14 @@
Copyright (C) 2020, 2021 Anastasis SARL
Anastasis is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
+ terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- You should have received a copy of the GNU Affero General Public License along with
+ You should have received a copy of the GNU General Public License along with
Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
*/
/**
@@ -55,7 +55,7 @@ struct ANASTASIS_Truth
/**
* Server salt used to derive hash from security answer
*/
- struct ANASTASIS_CRYPTO_QuestionSaltP salt;
+ struct ANASTASIS_CRYPTO_QuestionSaltP question_salt;
/**
* Url of the server
@@ -97,7 +97,8 @@ ANASTASIS_truth_from_json (const json_t *json)
&instructions),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("mime_type",
- &mime_type)),
+ &mime_type),
+ NULL),
GNUNET_JSON_spec_fixed_auto ("uuid",
&t->uuid),
GNUNET_JSON_spec_fixed_auto ("nonce",
@@ -106,8 +107,8 @@ ANASTASIS_truth_from_json (const json_t *json)
&t->key_share),
GNUNET_JSON_spec_fixed_auto ("truth_key",
&t->truth_key),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &t->salt),
+ GNUNET_JSON_spec_fixed_auto ("question_salt",
+ &t->question_salt),
GNUNET_JSON_spec_fixed_auto ("provider_salt",
&t->provider_salt),
GNUNET_JSON_spec_end ()
@@ -141,8 +142,8 @@ ANASTASIS_truth_to_json (const struct ANASTASIS_Truth *t)
&t->key_share),
GNUNET_JSON_pack_data_auto ("truth_key",
&t->truth_key),
- GNUNET_JSON_pack_data_auto ("salt",
- &t->salt),
+ GNUNET_JSON_pack_data_auto ("question_salt",
+ &t->question_salt),
GNUNET_JSON_pack_data_auto ("nonce",
&t->nonce),
GNUNET_JSON_pack_data_auto ("provider_salt",
@@ -251,7 +252,7 @@ ANASTASIS_truth_upload3 (struct GNUNET_CURL_Context *ctx,
truth_data_size);
ANASTASIS_CRYPTO_secure_answer_hash (answer,
&t->uuid,
- &t->salt,
+ &t->question_salt,
&nt);
ANASTASIS_CRYPTO_keyshare_encrypt (&t->key_share,
&tu->id,
@@ -313,7 +314,7 @@ ANASTASIS_truth_upload2 (
struct GNUNET_TIME_Relative pay_timeout,
const struct ANASTASIS_CRYPTO_NonceP *nonce,
const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid,
- const struct ANASTASIS_CRYPTO_QuestionSaltP *salt,
+ const struct ANASTASIS_CRYPTO_QuestionSaltP *question_salt,
const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
const struct ANASTASIS_CRYPTO_KeyShareP *key_share,
ANASTASIS_TruthCallback tc,
@@ -325,13 +326,13 @@ ANASTASIS_truth_upload2 (
t->url = GNUNET_strdup (provider_url);
t->type = GNUNET_strdup (type);
t->instructions = (NULL != instructions)
- ? GNUNET_strdup (instructions)
- : NULL;
+ ? GNUNET_strdup (instructions)
+ : NULL;
t->mime_type = (NULL != mime_type)
- ? GNUNET_strdup (mime_type)
- : NULL;
+ ? GNUNET_strdup (mime_type)
+ : NULL;
t->provider_salt = *provider_salt;
- t->salt = *salt;
+ t->question_salt = *question_salt;
t->nonce = *nonce;
t->uuid = *uuid;
t->truth_key = *truth_key;
@@ -442,7 +443,7 @@ struct ANASTASIS_Policy
/**
* Salt used to encrypt the master key
*/
- struct ANASTASIS_CRYPTO_MasterSaltP salt;
+ struct ANASTASIS_CRYPTO_MasterSaltP master_salt;
/**
* Array of truths
@@ -486,8 +487,8 @@ ANASTASIS_policy_create (const struct ANASTASIS_Truth *truths[],
p = GNUNET_new (struct ANASTASIS_Policy);
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &p->salt,
- sizeof (p->salt));
+ &p->master_salt,
+ sizeof (p->master_salt));
{
struct ANASTASIS_CRYPTO_KeyShareP key_shares[truths_len];
@@ -495,7 +496,7 @@ ANASTASIS_policy_create (const struct ANASTASIS_Truth *truths[],
key_shares[i] = truths[i]->key_share;
ANASTASIS_CRYPTO_policy_key_derive (key_shares,
truths_len,
- &p->salt,
+ &p->master_salt,
&p->policy_key);
}
p->truths = GNUNET_new_array (truths_len,
@@ -541,7 +542,7 @@ struct PolicyStoreState
* Server salt. Points into a truth object from which we got the
* salt.
*/
- struct ANASTASIS_CRYPTO_ProviderSaltP server_salt;
+ struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt;
/**
* The /policy POST operation handle.
@@ -571,7 +572,7 @@ struct PolicyStoreState
/**
* When will the policy expire at the provider.
*/
- struct GNUNET_TIME_Absolute policy_expiration;
+ struct GNUNET_TIME_Timestamp policy_expiration;
};
@@ -651,7 +652,7 @@ policy_store_cb (void *cls,
.ss = ANASTASIS_SHARE_STATUS_PROVIDER_FAILED,
.details.provider_failure.provider_url = pss->anastasis_url,
.details.provider_failure.http_status = ud->http_status,
- .details.provider_failure.ec = us,
+ .details.provider_failure.ec = ud->ec,
};
ss->src (ss->src_cls,
@@ -729,13 +730,13 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
size_t core_secret_size)
{
struct ANASTASIS_SecretShare *ss;
- struct ANASTASIS_CRYPTO_EncryptedMasterKeyP
- encrypted_master_keys[GNUNET_NZL (policies_len)];
- void *encrypted_core_secret;
+ struct ANASTASIS_CoreSecretEncryptionResult *cser;
json_t *dec_policies;
json_t *esc_methods;
size_t recovery_document_size;
char *recovery_document_str;
+ size_t meta_size;
+ void *meta;
if (0 == pss_length)
{
@@ -755,12 +756,10 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
for (unsigned int i = 0; i < policies_len; i++)
policy_keys[i] = policies[i]->policy_key;
- ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys,
- policies_len,
- core_secret,
- core_secret_size,
- &encrypted_core_secret,
- encrypted_master_keys);
+ cser = ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys,
+ policies_len,
+ core_secret,
+ core_secret_size);
}
dec_policies = json_array ();
GNUNET_assert (NULL != dec_policies);
@@ -780,15 +779,18 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
json_array_append_new (
dec_policies,
GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("master_key",
- &encrypted_master_keys[k]),
+ GNUNET_JSON_pack_data_varsize ("master_key",
+ cser->enc_master_keys[k],
+ cser->enc_master_key_sizes
+ [k]),
GNUNET_JSON_pack_array_steal ("uuids",
uuids),
- GNUNET_JSON_pack_data_auto ("salt",
- &policy->salt))));
+ GNUNET_JSON_pack_data_auto ("master_salt",
+ &policy->master_salt))));
}
esc_methods = json_array ();
+ GNUNET_assert (NULL != esc_methods);
for (unsigned int k = 0; k < policies_len; k++)
{
const struct ANASTASIS_Policy *policy = policies[k];
@@ -828,8 +830,8 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
pt->instructions),
GNUNET_JSON_pack_data_auto ("truth_key",
&pt->truth_key),
- GNUNET_JSON_pack_data_auto ("salt",
- &pt->salt),
+ GNUNET_JSON_pack_data_auto ("question_salt",
+ &pt->question_salt),
GNUNET_JSON_pack_data_auto ("provider_salt",
&pt->provider_salt),
GNUNET_JSON_pack_string ("escrow_type",
@@ -855,10 +857,11 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
GNUNET_JSON_pack_array_steal ("escrow_methods",
esc_methods),
GNUNET_JSON_pack_data_varsize ("encrypted_core_secret",
- encrypted_core_secret,
- core_secret_size));
+ cser->enc_core_secret,
+ cser->enc_core_secret_size));
GNUNET_assert (NULL != recovery_document);
- GNUNET_free (encrypted_core_secret);
+ ANASTASIS_CRYPTO_destroy_encrypted_core_secret (cser);
+ cser = NULL;
rd_str = json_dumps (recovery_document,
JSON_COMPACT | JSON_SORT_KEYS);
@@ -889,20 +892,39 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
recovery_document_str = (char *) cbuf;
}
+ meta_size = sizeof (struct GNUNET_HashCode);
+ if (NULL != secret_name)
+ meta_size += strlen (secret_name) + 1;
+ meta = GNUNET_malloc (meta_size);
+ GNUNET_CRYPTO_hash (recovery_document_str,
+ recovery_document_size,
+ (struct GNUNET_HashCode *) meta);
+ if (NULL != secret_name)
+ memcpy (meta + sizeof (struct GNUNET_HashCode),
+ secret_name,
+ strlen (secret_name) + 1);
+
for (unsigned int l = 0; l < ss->pss_length; l++)
{
struct PolicyStoreState *pss = &ss->pss[l];
void *recovery_data;
size_t recovery_data_size;
struct ANASTASIS_CRYPTO_AccountPrivateKeyP anastasis_priv;
+ size_t enc_meta_size = 0;
+ void *enc_meta = NULL;
pss->ss = ss;
pss->anastasis_url = GNUNET_strdup (providers[l].provider_url);
- pss->server_salt = providers[l].provider_salt;
+ pss->provider_salt = providers[l].provider_salt;
pss->payment_secret = providers[l].payment_secret;
ANASTASIS_CRYPTO_user_identifier_derive (id_data,
- &pss->server_salt,
+ &pss->provider_salt,
&pss->id);
+ ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id,
+ meta,
+ meta_size,
+ &enc_meta,
+ &enc_meta_size);
ANASTASIS_CRYPTO_account_private_key_derive (&pss->id,
&anastasis_priv);
ANASTASIS_CRYPTO_recovery_document_encrypt (&pss->id,
@@ -919,6 +941,8 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
&anastasis_priv,
recovery_data,
recovery_data_size,
+ enc_meta,
+ enc_meta_size,
payment_years_requested,
(! GNUNET_is_zero (&pss->payment_secret))
? &pss->payment_secret
@@ -927,14 +951,17 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
&policy_store_cb,
pss);
GNUNET_free (recovery_data);
+ GNUNET_free (enc_meta);
if (NULL == pss->pso)
{
GNUNET_break (0);
ANASTASIS_secret_share_cancel (ss);
GNUNET_free (recovery_document_str);
+ GNUNET_free (meta);
return NULL;
}
}
+ GNUNET_free (meta);
GNUNET_free (recovery_document_str);
return ss;
}
diff --git a/src/lib/anastasis_meta.c b/src/lib/anastasis_meta.c
new file mode 100644
index 0000000..ae20db5
--- /dev/null
+++ b/src/lib/anastasis_meta.c
@@ -0,0 +1,178 @@
+/*
+ This file is part of Anastasis
+ Copyright (C) 2022 Anastasis SARL
+
+ Anastasis is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @brief anastasis client api to get recovery document meta data
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "anastasis.h"
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_merchant_service.h>
+
+
+/**
+ * Handle for a version check operation.
+ */
+struct ANASTASIS_VersionCheck
+{
+ /**
+ * Function to call with results.
+ */
+ ANASTASIS_MetaPolicyCallback mpc;
+
+ /**
+ * Closure for @e mpc.
+ */
+ void *mpc_cls;
+
+ /**
+ * Handle for the actual REST operation.
+ */
+ struct ANASTASIS_PolicyMetaLookupOperation *plm;
+
+ /**
+ * User identifier (needed to decrypt).
+ */
+ struct ANASTASIS_CRYPTO_UserIdentifierP id;
+};
+
+
+/**
+ * Function called with results from a GET /policy/$POL/meta request
+ *
+ * @param cls closure with the `struct ANASTASIS_VersionCheck *`
+ * @param dd the response details
+ */
+static void
+meta_cb (
+ void *cls,
+ const struct ANASTASIS_MetaDownloadDetails *dd)
+{
+ struct ANASTASIS_VersionCheck *vc = cls;
+
+ vc->plm = NULL;
+ if (MHD_HTTP_OK != dd->http_status)
+ {
+ vc->mpc (vc->mpc_cls,
+ 0,
+ GNUNET_TIME_UNIT_ZERO_TS,
+ NULL,
+ NULL);
+ ANASTASIS_recovery_get_versions_cancel (vc);
+ return;
+ }
+ for (size_t i = 0; i<dd->details.ok.metas_length; i++)
+ {
+ const struct ANASTASIS_MetaDataEntry *meta
+ = &dd->details.ok.metas[i];
+ const char *secret_name = NULL;
+ const struct GNUNET_HashCode *eph;
+ void *dec;
+ size_t dec_len;
+
+ if (GNUNET_OK !=
+ ANASTASIS_CRYPTO_recovery_metadata_decrypt (
+ &vc->id,
+ meta->meta_data,
+ meta->meta_data_size,
+ &dec,
+ &dec_len))
+ {
+ GNUNET_break_op (0);
+ continue;
+ }
+ if (sizeof (*eph) > dec_len)
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (dec);
+ continue;
+ }
+ eph = dec;
+ if (sizeof (*eph) < dec_len)
+ {
+ secret_name = (const char *) &eph[1];
+ dec_len -= sizeof (*eph);
+ if ('\0' != secret_name[dec_len - 1])
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (dec);
+ continue;
+ }
+ }
+ vc->mpc (vc->mpc_cls,
+ meta->version,
+ meta->server_time,
+ eph,
+ secret_name);
+ GNUNET_free (dec);
+ }
+ vc->mpc (vc->mpc_cls,
+ 0,
+ GNUNET_TIME_UNIT_ZERO_TS,
+ NULL,
+ NULL);
+ ANASTASIS_recovery_get_versions_cancel (vc);
+}
+
+
+struct ANASTASIS_VersionCheck *
+ANASTASIS_recovery_get_versions (
+ struct GNUNET_CURL_Context *ctx,
+ const json_t *id_data,
+ unsigned int max_version,
+ const char *anastasis_provider_url,
+ const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
+ ANASTASIS_MetaPolicyCallback mpc,
+ void *mpc_cls)
+{
+ struct ANASTASIS_VersionCheck *vc;
+ struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub;
+
+ vc = GNUNET_new (struct ANASTASIS_VersionCheck);
+ vc->mpc = mpc;
+ vc->mpc_cls = mpc_cls;
+ ANASTASIS_CRYPTO_user_identifier_derive (id_data,
+ provider_salt,
+ &vc->id);
+ ANASTASIS_CRYPTO_account_public_key_derive (&vc->id,
+ &account_pub);
+ vc->plm = ANASTASIS_policy_meta_lookup (ctx,
+ anastasis_provider_url,
+ &account_pub,
+ max_version,
+ &meta_cb,
+ vc);
+ if (NULL == vc->plm)
+ {
+ GNUNET_break (0);
+ GNUNET_free (vc);
+ return NULL;
+ }
+ return vc;
+}
+
+
+void
+ANASTASIS_recovery_get_versions_cancel (struct ANASTASIS_VersionCheck *vc)
+{
+ if (NULL != vc->plm)
+ {
+ ANASTASIS_policy_meta_lookup_cancel (vc->plm);
+ vc->plm = NULL;
+ }
+ GNUNET_free (vc);
+}
diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c
index ac10418..41f35a5 100644
--- a/src/lib/anastasis_recovery.c
+++ b/src/lib/anastasis_recovery.c
@@ -3,14 +3,14 @@
Copyright (C) 2020, 2021 Anastasis SARL
Anastasis is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
+ terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- You should have received a copy of the GNU Affero General Public License along with
+ You should have received a copy of the GNU General Public License along with
Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
*/
/**
@@ -47,7 +47,7 @@ struct ANASTASIS_Challenge
/**
* Salt; used to derive hash from security question answers.
*/
- struct ANASTASIS_CRYPTO_QuestionSaltP salt;
+ struct ANASTASIS_CRYPTO_QuestionSaltP question_salt;
/**
* Provider salt; used to derive our key material from our identity
@@ -63,16 +63,27 @@ struct ANASTASIS_Challenge
/**
* Callback which gives back the instructions and a status code of
- * the request to the user when answering a challenge was initiated.
+ * the request to the user when answering a challenge.
*/
ANASTASIS_AnswerFeedback af;
/**
- * Closure for the challenge callback
+ * Closure for @e af.
*/
void *af_cls;
/**
+ * Callback which gives back the instructions and a status code of
+ * the request to the user when initiating a challenge.
+ */
+ ANASTASIS_ChallengeStartFeedback csf;
+
+ /**
+ * Closure for @e csf.
+ */
+ void *csf_cls;
+
+ /**
* Defines the base URL of the Anastasis provider used for the challenge.
*/
char *url;
@@ -99,9 +110,14 @@ struct ANASTASIS_Challenge
struct ANASTASIS_Recovery *recovery;
/**
- * keyshare lookup operation
+ * Handle for the /truth/$TID/challenge request.
+ */
+ struct ANASTASIS_TruthChallengeOperation *tco;
+
+ /**
+ * Handle for the /truth/$TID/solve request.
*/
- struct ANASTASIS_KeyShareLookupOperation *kslo;
+ struct ANASTASIS_TruthSolveOperation *tso;
};
@@ -118,14 +134,19 @@ struct DecryptionPolicy
struct ANASTASIS_DecryptionPolicy pub_details;
/**
- * Encrypted masterkey (encrypted with the policy key).
+ * Encrypted master key (encrypted with the policy key).
*/
- struct ANASTASIS_CRYPTO_EncryptedMasterKeyP emk;
+ void *emk;
+
+ /**
+ * Size of the encrypted master key.
+ */
+ size_t emk_size;
/**
* Salt used to decrypt master key.
*/
- struct ANASTASIS_CRYPTO_MasterSaltP salt;
+ struct ANASTASIS_CRYPTO_MasterSaltP master_salt;
};
@@ -233,161 +254,140 @@ struct ANASTASIS_Recovery
/**
- * Function called with the results of a #ANASTASIS_keyshare_lookup().
+ * Function called with the results of a #ANASTASIS_challenge_start().
*
* @param cls closure
* @param dd details about the lookup operation
*/
static void
-keyshare_lookup_cb (void *cls,
- const struct ANASTASIS_KeyShareDownloadDetails *dd)
+truth_challenge_cb (void *cls,
+ const struct ANASTASIS_TruthChallengeDetails *tcd)
{
struct ANASTASIS_Challenge *c = cls;
- struct ANASTASIS_Recovery *recovery = c->recovery;
- struct ANASTASIS_CRYPTO_UserIdentifierP id;
- struct DecryptionPolicy *rdps;
-
- c->kslo = NULL;
- switch (dd->status)
+ struct ANASTASIS_ChallengeStartResponse csr = {
+ .challenge = c,
+ .ec = tcd->ec,
+ .http_status = tcd->http_status
+ };
+
+ c->tco = NULL;
+ switch (tcd->http_status)
{
- case ANASTASIS_KSD_SUCCESS:
- break;
- case ANASTASIS_KSD_PAYMENT_REQUIRED:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED,
- .challenge = c,
- .details.payment_required.taler_pay_uri
- = dd->details.payment_required.taler_pay_uri,
- .details.payment_required.payment_secret
- = dd->details.payment_required.payment_secret
- };
-
- c->af (c->af_cls,
- &csr);
- return;
- }
- case ANASTASIS_KSD_INVALID_ANSWER:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS,
- .challenge = c,
- .details.open_challenge.body
- = dd->details.open_challenge.body,
- .details.open_challenge.content_type
- = dd->details.open_challenge.content_type,
- .details.open_challenge.body_size
- = dd->details.open_challenge.body_size,
- .details.open_challenge.http_status
- = dd->details.open_challenge.http_status
- };
-
- c->af (c->af_cls,
- &csr);
- return;
- }
- case ANASTASIS_KSD_REDIRECT_FOR_AUTHENTICATION:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION,
- .challenge = c,
- .details.redirect_url
- = dd->details.redirect_url
- };
-
- c->af (c->af_cls,
- &csr);
- return;
- }
- case ANASTASIS_KSD_TRUTH_UNKNOWN:
+ case MHD_HTTP_OK:
+ switch (tcd->details.success.cs)
{
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_TRUTH_UNKNOWN,
- .challenge = c
- };
-
- c->af (c->af_cls,
- &csr);
- return;
+ case ANASTASIS_CS_FILE_WRITTEN:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_FILENAME_PROVIDED;
+ csr.details.tan_filename
+ = tcd->details.success.details.challenge_filename;
+ break;
+ case ANASTASIS_CS_TAN_SENT:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_TAN_SENT_HINT_PROVIDED;
+ csr.details.tan_address_hint
+ = tcd->details.success.details.tan_address_hint;
+ break;
+ case ANASTASIS_CS_TAN_ALREADY_SENT:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_TAN_ALREADY_SENT;
+ break;
+ case ANASTASIS_CS_WIRE_FUNDS:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_BANK_TRANSFER_REQUIRED;
+ csr.details.bank_transfer_required
+ = tcd->details.success.details.wire_funds;
+ break;
}
- case ANASTASIS_KSD_RATE_LIMIT_EXCEEDED:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED,
- .challenge = c
- };
+ break;
+ case MHD_HTTP_PAYMENT_REQUIRED:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_PAYMENT_REQUIRED;
+ csr.details.payment_required.taler_pay_uri
+ = tcd->details.payment_required.payment_request;
+ csr.details.payment_required.payment_secret
+ = tcd->details.payment_required.ps;
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_TRUTH_UNKNOWN;
+ break;
+ default:
+ csr.cs = ANASTASIS_CHALLENGE_START_STATUS_SERVER_FAILURE;
+ break;
+ }
+ c->csf (c->csf_cls,
+ &csr);
+}
- c->af (c->af_cls,
- &csr);
- return;
- }
- case ANASTASIS_KSD_SERVER_ERROR:
- case ANASTASIS_KSD_CLIENT_FAILURE:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE,
- .challenge = c,
- .details.server_failure.ec
- = dd->details.server_failure.ec,
- .details.server_failure.http_status
- = dd->details.server_failure.http_status
- };
- c->af (c->af_cls,
- &csr);
- return;
- }
- case ANASTASIS_KSD_AUTHENTICATION_TIMEOUT:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_AUTH_TIMEOUT,
- .challenge = c,
- .details.server_failure.ec
- = dd->details.server_failure.ec,
- .details.server_failure.http_status
- = dd->details.server_failure.http_status
- };
+/**
+ * Function called with the results of a #ANASTASIS_truth_solve().
+ *
+ * @param cls closure
+ * @param tsr details about the solution response
+ */
+static void
+truth_solve_cb (void *cls,
+ const struct ANASTASIS_TruthSolveReply *tsr)
+{
+ struct ANASTASIS_Challenge *c = cls;
+ struct ANASTASIS_Recovery *recovery = c->recovery;
+ struct ANASTASIS_CRYPTO_UserIdentifierP id;
+ struct DecryptionPolicy *rdps;
+ struct ANASTASIS_ChallengeAnswerResponse csr = {
+ .challenge = c,
+ .ec = tsr->ec,
+ .http_status = tsr->http_status
+ };
- c->ci.async = true;
- c->af (c->af_cls,
- &csr);
- return;
- }
- case ANASTASIS_KSD_EXTERNAL_CHALLENGE_INSTRUCTIONS:
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS,
- .challenge = c,
- .details.external_challenge = dd->details.external_challenge
- };
- c->af (c->af_cls,
- &csr);
- return;
- }
+ c->tso = NULL;
+ switch (tsr->http_status)
+ {
+ case MHD_HTTP_OK:
+ break;
+ case MHD_HTTP_PAYMENT_REQUIRED:
+ csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_PAYMENT_REQUIRED;
+ csr.details.payment_required.taler_pay_uri
+ = tsr->details.payment_required.payment_request;
+ csr.details.payment_required.payment_secret
+ = tsr->details.payment_required.ps;
+ c->af (c->af_cls,
+ &csr);
+ return;
+ case MHD_HTTP_FORBIDDEN:
+ csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_INVALID_ANSWER;
+ c->af (c->af_cls,
+ &csr);
+ return;
+ case MHD_HTTP_NOT_FOUND:
+ csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_TRUTH_UNKNOWN;
+ c->af (c->af_cls,
+ &csr);
+ return;
+ case MHD_HTTP_TOO_MANY_REQUESTS:
+ csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_RATE_LIMIT_EXCEEDED;
+ csr.details.rate_limit_exceeded.request_limit
+ = tsr->details.too_many_requests.request_limit;
+ csr.details.rate_limit_exceeded.request_frequency
+ = tsr->details.too_many_requests.request_frequency;
+ c->af (c->af_cls,
+ &csr);
+ return;
+ default:
+ csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_SERVER_FAILURE;
+ c->af (c->af_cls,
+ &csr);
+ return;
}
- GNUNET_assert (NULL != dd);
ANASTASIS_CRYPTO_user_identifier_derive (recovery->id_data,
&c->provider_salt,
&id);
- ANASTASIS_CRYPTO_keyshare_decrypt (&dd->details.eks,
+ ANASTASIS_CRYPTO_keyshare_decrypt (&tsr->details.success.eks,
&id,
c->answer,
&c->key_share);
recovery->solved_challenges[recovery->solved_challenge_pos++] = c;
-
- {
- struct ANASTASIS_ChallengeStartResponse csr = {
- .cs = ANASTASIS_CHALLENGE_STATUS_SOLVED,
- .challenge = c
- };
-
- c->ci.solved = true;
- c->af (c->af_cls,
- &csr);
- }
-
+ c->ci.solved = true;
+ csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_SOLVED;
+ c->af (c->af_cls,
+ &csr);
/* Check if there is a policy for which all challenges have
been satisfied, if so, store it in 'rdps'. */
@@ -437,9 +437,12 @@ keyshare_lookup_cb (void *cls,
key_shares[l] = recovery->solved_challenges[m]->key_share;
ANASTASIS_CRYPTO_policy_key_derive (key_shares,
rdps->pub_details.challenges_length,
- &rdps->salt,
+ &rdps->master_salt,
&policy_key);
- ANASTASIS_CRYPTO_core_secret_recover (&rdps->emk,
+ GNUNET_assert (NULL != rdps->emk);
+ GNUNET_assert (rdps->emk_size > 0);
+ ANASTASIS_CRYPTO_core_secret_recover (rdps->emk,
+ rdps->emk_size,
&policy_key,
recovery->enc_core_secret,
recovery->enc_core_secret_size,
@@ -462,36 +465,70 @@ ANASTASIS_challenge_get_details (struct ANASTASIS_Challenge *challenge)
}
-int
+enum GNUNET_GenericReturnValue
ANASTASIS_challenge_start (struct ANASTASIS_Challenge *c,
const struct ANASTASIS_PaymentSecretP *psp,
- struct GNUNET_TIME_Relative timeout,
- const struct GNUNET_HashCode *hashed_answer,
- ANASTASIS_AnswerFeedback af,
- void *af_cls)
+ ANASTASIS_ChallengeStartFeedback csf,
+ void *csf_cls)
+{
+ if (c->ci.solved)
+ {
+ GNUNET_break (0);
+ return GNUNET_NO; /* already solved */
+ }
+ if (NULL != c->tco)
+ {
+ GNUNET_break (0);
+ return GNUNET_NO; /* already solving */
+ }
+ c->csf = csf;
+ c->csf_cls = csf_cls;
+ c->tco = ANASTASIS_truth_challenge (c->recovery->ctx,
+ c->url,
+ &c->ci.uuid,
+ &c->truth_key,
+ psp,
+ &truth_challenge_cb,
+ c);
+ if (NULL == c->tco)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+enum GNUNET_GenericReturnValue
+ANASTASIS_challenge_answer3 (struct ANASTASIS_Challenge *c,
+ const struct ANASTASIS_PaymentSecretP *psp,
+ struct GNUNET_TIME_Relative timeout,
+ const struct GNUNET_HashCode *hashed_answer,
+ ANASTASIS_AnswerFeedback af,
+ void *af_cls)
{
if (c->ci.solved)
{
GNUNET_break (0);
return GNUNET_NO; /* already solved */
}
- if (NULL != c->kslo)
+ if (NULL != c->tso)
{
GNUNET_break (0);
return GNUNET_NO; /* already solving */
}
c->af = af;
c->af_cls = af_cls;
- c->kslo = ANASTASIS_keyshare_lookup (c->recovery->ctx,
- c->url,
- &c->ci.uuid,
- &c->truth_key,
- psp,
- timeout,
- hashed_answer,
- &keyshare_lookup_cb,
- c);
- if (NULL == c->kslo)
+ c->tso = ANASTASIS_truth_solve (c->recovery->ctx,
+ c->url,
+ &c->ci.uuid,
+ &c->truth_key,
+ psp,
+ timeout,
+ hashed_answer,
+ &truth_solve_cb,
+ c);
+ if (NULL == c->tso)
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -500,7 +537,7 @@ ANASTASIS_challenge_start (struct ANASTASIS_Challenge *c,
}
-int
+enum GNUNET_GenericReturnValue
ANASTASIS_challenge_answer (
struct ANASTASIS_Challenge *c,
const struct ANASTASIS_PaymentSecretP *psp,
@@ -512,21 +549,24 @@ ANASTASIS_challenge_answer (
struct GNUNET_HashCode hashed_answer;
GNUNET_free (c->answer);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Answer to challenge is `%s'\n",
+ answer_str);
c->answer = GNUNET_strdup (answer_str);
ANASTASIS_CRYPTO_secure_answer_hash (answer_str,
&c->ci.uuid,
- &c->salt,
+ &c->question_salt,
&hashed_answer);
- return ANASTASIS_challenge_start (c,
- psp,
- timeout,
- &hashed_answer,
- af,
- af_cls);
+ return ANASTASIS_challenge_answer3 (c,
+ psp,
+ timeout,
+ &hashed_answer,
+ af,
+ af_cls);
}
-int
+enum GNUNET_GenericReturnValue
ANASTASIS_challenge_answer2 (struct ANASTASIS_Challenge *c,
const struct ANASTASIS_PaymentSecretP *psp,
struct GNUNET_TIME_Relative timeout,
@@ -536,27 +576,33 @@ ANASTASIS_challenge_answer2 (struct ANASTASIS_Challenge *c,
{
struct GNUNET_HashCode answer_s;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Answer to challenge is %llu\n",
+ (unsigned long long) answer);
ANASTASIS_hash_answer (answer,
&answer_s);
- return ANASTASIS_challenge_start (c,
- psp,
- timeout,
- &answer_s,
- af,
- af_cls);
+ return ANASTASIS_challenge_answer3 (c,
+ psp,
+ timeout,
+ &answer_s,
+ af,
+ af_cls);
}
void
ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c)
{
- if (NULL == c->kslo)
+ if (NULL != c->tso)
{
- GNUNET_break (0);
- return;
+ ANASTASIS_truth_solve_cancel (c->tso);
+ c->tso = NULL;
+ }
+ if (NULL != c->tco)
+ {
+ ANASTASIS_truth_challenge_cancel (c->tco);
+ c->tco = NULL;
}
- ANASTASIS_keyshare_lookup_cancel (c->kslo);
- c->kslo = NULL;
c->af = NULL;
c->af_cls = NULL;
}
@@ -566,23 +612,22 @@ ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c)
* Function called with the results of a #ANASTASIS_policy_lookup()
*
* @param cls closure
- * @param http_status HTTp status code.
* @param dd details about the lookup operation
*/
static void
policy_lookup_cb (void *cls,
- unsigned int http_status,
const struct ANASTASIS_DownloadDetails *dd)
{
struct ANASTASIS_Recovery *r = cls;
void *plaintext;
size_t size_plaintext;
json_error_t json_error;
- json_t *dec_policies;
- json_t *esc_methods;
+ const json_t *dec_policies;
+ const json_t *esc_methods;
+ json_t *recovery_document;
r->plo = NULL;
- switch (http_status)
+ switch (dd->http_status)
{
case MHD_HTTP_OK:
break;
@@ -614,7 +659,7 @@ policy_lookup_cb (void *cls,
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u in %s:%u\n",
- http_status,
+ dd->http_status,
__FILE__,
__LINE__);
r->csc (r->csc_cls,
@@ -624,7 +669,7 @@ policy_lookup_cb (void *cls,
ANASTASIS_recovery_abort (r);
return;
}
- if (NULL == dd->policy)
+ if (NULL == dd->details.ok.policy)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"No recovery data available");
@@ -636,8 +681,8 @@ policy_lookup_cb (void *cls,
return;
}
ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id,
- dd->policy,
- dd->policy_size,
+ dd->details.ok.policy,
+ dd->details.ok.policy_size,
&plaintext,
&size_plaintext);
if (size_plaintext < sizeof (uint32_t))
@@ -652,7 +697,6 @@ policy_lookup_cb (void *cls,
return;
}
{
- json_t *recovery_document;
uint32_t be_size;
uLongf pt_size;
char *pt;
@@ -715,13 +759,14 @@ policy_lookup_cb (void *cls,
{
const char *secret_name = NULL;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("policies",
- &dec_policies),
- GNUNET_JSON_spec_json ("escrow_methods",
- &esc_methods),
+ GNUNET_JSON_spec_array_const ("policies",
+ &dec_policies),
+ GNUNET_JSON_spec_array_const ("escrow_methods",
+ &esc_methods),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("secret_name",
- &secret_name)),
+ &secret_name),
+ NULL),
GNUNET_JSON_spec_varsize ("encrypted_core_secret",
&r->enc_core_secret,
&r->enc_core_secret_size),
@@ -737,13 +782,11 @@ policy_lookup_cb (void *cls,
json_dumpf (recovery_document,
stderr,
0);
- json_decref (recovery_document);
r->csc (r->csc_cls,
ANASTASIS_RS_POLICY_MALFORMED_JSON,
NULL,
0);
- ANASTASIS_recovery_abort (r);
- return;
+ goto cleanup;
}
if (NULL != secret_name)
{
@@ -752,22 +795,39 @@ policy_lookup_cb (void *cls,
r->ri.secret_name = r->secret_name;
}
}
- json_decref (recovery_document);
}
- r->ri.version = dd->version;
- r->ri.cs_len = json_array_size (esc_methods);
- r->ri.dps_len = json_array_size (dec_policies);
- r->ri.dps = GNUNET_new_array (r->ri.dps_len,
- struct ANASTASIS_DecryptionPolicy *);
- r->dps = GNUNET_new_array (r->ri.dps_len,
- struct DecryptionPolicy);
- r->solved_challenges = GNUNET_new_array (r->ri.cs_len,
- struct ANASTASIS_Challenge *);
- r->ri.cs = GNUNET_new_array (r->ri.cs_len,
- struct ANASTASIS_Challenge *);
- r->cs = GNUNET_new_array (r->ri.cs_len,
- struct ANASTASIS_Challenge);
+ if ( (json_array_size (esc_methods) > UINT_MAX) ||
+ (json_array_size (dec_policies) > UINT_MAX) )
+ {
+ GNUNET_break_op (0);
+ r->csc (r->csc_cls,
+ ANASTASIS_RS_POLICY_DOWNLOAD_TOO_BIG,
+ NULL,
+ 0);
+ goto cleanup;
+ }
+
+ r->ri.version = dd->details.ok.version;
+ r->ri.cs_len
+ = (unsigned int) json_array_size (esc_methods);
+ r->ri.dps_len
+ = (unsigned int) json_array_size (dec_policies);
+ r->ri.dps
+ = GNUNET_new_array (r->ri.dps_len,
+ struct ANASTASIS_DecryptionPolicy *);
+ r->dps
+ = GNUNET_new_array (r->ri.dps_len,
+ struct DecryptionPolicy);
+ r->solved_challenges
+ = GNUNET_new_array (r->ri.cs_len,
+ struct ANASTASIS_Challenge *);
+ r->ri.cs
+ = GNUNET_new_array (r->ri.cs_len,
+ struct ANASTASIS_Challenge *);
+ r->cs
+ = GNUNET_new_array (r->ri.cs_len,
+ struct ANASTASIS_Challenge);
for (unsigned int i = 0; i < r->ri.cs_len; i++)
{
struct ANASTASIS_Challenge *cs = &r->cs[i];
@@ -777,14 +837,14 @@ policy_lookup_cb (void *cls,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("uuid",
&cs->ci.uuid),
- GNUNET_JSON_spec_string ("url",
+ TALER_JSON_spec_web_url ("url",
&url),
GNUNET_JSON_spec_string ("instructions",
&instructions),
GNUNET_JSON_spec_fixed_auto ("truth_key",
&cs->truth_key),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &cs->salt),
+ GNUNET_JSON_spec_fixed_auto ("question_salt",
+ &cs->question_salt),
GNUNET_JSON_spec_fixed_auto ("provider_salt",
&cs->provider_salt),
GNUNET_JSON_spec_string ("escrow_type",
@@ -801,14 +861,11 @@ policy_lookup_cb (void *cls,
NULL, NULL))
{
GNUNET_break_op (0);
- json_decref (esc_methods);
- json_decref (dec_policies);
r->csc (r->csc_cls,
ANASTASIS_RS_POLICY_MALFORMED_JSON,
NULL,
0);
- ANASTASIS_recovery_abort (r);
- return;
+ goto cleanup;
}
cs->url = GNUNET_strdup (url);
cs->type = GNUNET_strdup (escrow_type);
@@ -817,44 +874,53 @@ policy_lookup_cb (void *cls,
cs->instructions = GNUNET_strdup (instructions);
cs->ci.instructions = cs->instructions;
}
- json_decref (esc_methods);
for (unsigned int j = 0; j < r->ri.dps_len; j++)
{
struct DecryptionPolicy *dp = &r->dps[j];
- json_t *uuids = NULL;
+ const json_t *uuids;
json_t *uuid;
size_t n_index;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("master_key",
- &dp->emk),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &dp->salt),
- GNUNET_JSON_spec_json ("uuids",
- &uuids),
+ GNUNET_JSON_spec_varsize ("master_key",
+ &dp->emk,
+ &dp->emk_size),
+ GNUNET_JSON_spec_fixed_auto ("master_salt",
+ &dp->master_salt),
+ GNUNET_JSON_spec_array_const ("uuids",
+ &uuids),
GNUNET_JSON_spec_end ()
};
r->ri.dps[j] = &r->dps[j].pub_details;
- if ( (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (dec_policies,
- j),
- spec,
- NULL, NULL)) ||
- (! json_is_array (uuids)) )
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json_array_get (dec_policies,
+ j),
+ spec,
+ NULL, NULL))
{
GNUNET_break_op (0);
- json_decref (uuids);
- json_decref (dec_policies);
r->csc (r->csc_cls,
ANASTASIS_RS_POLICY_MALFORMED_JSON,
NULL,
0);
- ANASTASIS_recovery_abort (r);
- return;
+ goto cleanup;
}
- dp->pub_details.challenges_length = json_array_size (uuids);
+ GNUNET_assert (NULL != dp->emk);
+ GNUNET_assert (dp->emk_size > 0);
+
+ if (json_array_size (uuids) > UINT_MAX)
+ {
+ GNUNET_break_op (0);
+ r->csc (r->csc_cls,
+ ANASTASIS_RS_POLICY_MALFORMED_JSON,
+ NULL,
+ 0);
+ goto cleanup;
+ }
+ dp->pub_details.challenges_length
+ = (unsigned int) json_array_size (uuids);
dp->pub_details.challenges
= GNUNET_new_array (dp->pub_details.challenges_length,
struct ANASTASIS_Challenge *);
@@ -873,14 +939,11 @@ policy_lookup_cb (void *cls,
sizeof (uuid))) )
{
GNUNET_break_op (0);
- json_decref (dec_policies);
- json_decref (uuids);
r->csc (r->csc_cls,
ANASTASIS_RS_POLICY_MALFORMED_JSON,
NULL,
0);
- ANASTASIS_recovery_abort (r);
- return;
+ goto cleanup;
}
for (unsigned int i = 0; i<r->ri.cs_len; i++)
{
@@ -895,21 +958,21 @@ policy_lookup_cb (void *cls,
if (! found)
{
GNUNET_break_op (0);
- json_decref (dec_policies);
- json_decref (uuids);
r->csc (r->csc_cls,
ANASTASIS_RS_POLICY_MALFORMED_JSON,
NULL,
0);
- ANASTASIS_recovery_abort (r);
- return;
+ goto cleanup;
}
}
- json_decref (uuids);
}
- json_decref (dec_policies);
r->pc (r->pc_cls,
&r->ri);
+ json_decref (recovery_document);
+ return;
+cleanup:
+ ANASTASIS_recovery_abort (r);
+ json_decref (recovery_document);
}
@@ -997,11 +1060,13 @@ ANASTASIS_recovery_serialize (const struct ANASTASIS_Recovery *r)
json_array_append_new (c_arr,
cs));
}
+ GNUNET_assert (NULL != dp->emk);
dps = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("emk",
- &dp->emk),
- GNUNET_JSON_pack_data_auto ("salt",
- &dp->salt),
+ GNUNET_JSON_pack_data_varsize ("encrypted_master_key",
+ dp->emk,
+ dp->emk_size),
+ GNUNET_JSON_pack_data_auto ("master_salt",
+ &dp->master_salt),
GNUNET_JSON_pack_array_steal ("challenges",
c_arr));
GNUNET_assert (0 ==
@@ -1018,10 +1083,12 @@ ANASTASIS_recovery_serialize (const struct ANASTASIS_Recovery *r)
cs = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("uuid",
&c->ci.uuid),
+ GNUNET_JSON_pack_string ("uuid-display",
+ ANASTASIS_CRYPTO_uuid2s (&c->ci.uuid)),
GNUNET_JSON_pack_data_auto ("truth_key",
&c->truth_key),
- GNUNET_JSON_pack_data_auto ("salt",
- &c->salt),
+ GNUNET_JSON_pack_data_auto ("question_salt",
+ &c->question_salt),
GNUNET_JSON_pack_data_auto ("provider_salt",
&c->provider_salt),
GNUNET_JSON_pack_allow_null (
@@ -1048,9 +1115,9 @@ ANASTASIS_recovery_serialize (const struct ANASTASIS_Recovery *r)
return GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("id",
&r->id),
- GNUNET_JSON_pack_array_steal ("dps",
+ GNUNET_JSON_pack_array_steal ("decryption_policies",
dps_arr),
- GNUNET_JSON_pack_array_steal ("cs",
+ GNUNET_JSON_pack_array_steal ("challenges",
cs_arr),
GNUNET_JSON_pack_uint64 ("version",
r->ri.version),
@@ -1061,34 +1128,43 @@ ANASTASIS_recovery_serialize (const struct ANASTASIS_Recovery *r)
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("secret_name",
r->secret_name)),
- GNUNET_JSON_pack_data_varsize ("core_secret",
+ GNUNET_JSON_pack_data_varsize ("encrypted_core_secret",
r->enc_core_secret,
r->enc_core_secret_size));
}
/**
- * Parse the @a cs_array and update @a r accordingly
+ * Parse the @a cs_array with information about
+ * the various challenges and their solution state
+ * and update @a r accordingly
*
* @param[in,out] r recovery information to update
* @param cs_arr serialized data to parse
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
parse_cs_array (struct ANASTASIS_Recovery *r,
- json_t *cs_arr)
+ const json_t *cs_arr)
{
json_t *cs;
- unsigned int n_index;
+ size_t n_index;
if (! json_is_array (cs_arr))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- r->ri.cs_len = json_array_size (cs_arr);
- r->solved_challenges = GNUNET_new_array (r->ri.cs_len,
- struct ANASTASIS_Challenge *);
+ if (json_array_size (cs_arr) > UINT_MAX)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ r->ri.cs_len
+ = (unsigned int) json_array_size (cs_arr);
+ r->solved_challenges
+ = GNUNET_new_array (r->ri.cs_len,
+ struct ANASTASIS_Challenge *);
r->ri.cs = GNUNET_new_array (r->ri.cs_len,
struct ANASTASIS_Challenge *);
r->cs = GNUNET_new_array (r->ri.cs_len,
@@ -1099,27 +1175,30 @@ parse_cs_array (struct ANASTASIS_Recovery *r,
const char *instructions;
const char *url;
const char *escrow_type;
+ bool no_key_share;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("uuid",
&c->ci.uuid),
- GNUNET_JSON_spec_string ("url",
+ TALER_JSON_spec_web_url ("url",
&url),
GNUNET_JSON_spec_string ("instructions",
&instructions),
GNUNET_JSON_spec_fixed_auto ("truth_key",
&c->truth_key),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &c->salt),
+ GNUNET_JSON_spec_fixed_auto ("question_salt",
+ &c->question_salt),
GNUNET_JSON_spec_fixed_auto ("provider_salt",
&c->provider_salt),
GNUNET_JSON_spec_string ("type",
&escrow_type),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_bool ("async",
- &c->ci.async)),
+ &c->ci.async),
+ NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("key_share",
- &c->key_share)),
+ &c->key_share),
+ &no_key_share),
GNUNET_JSON_spec_end ()
};
@@ -1139,44 +1218,43 @@ parse_cs_array (struct ANASTASIS_Recovery *r,
c->instructions = GNUNET_strdup (instructions);
c->ci.instructions = c->instructions;
c->ci.provider_url = c->url;
+ if (! no_key_share)
{
- json_t *ks;
-
- ks = json_object_get (cs,
- "key_share");
- if ( (NULL != ks) &&
- (! json_is_null (ks)) )
- {
- c->ci.solved = true;
- r->solved_challenges[r->solved_challenge_pos++] = c;
- }
+ c->ci.solved = true;
+ r->solved_challenges[r->solved_challenge_pos++] = c;
}
}
-
return GNUNET_OK;
}
/**
- * Parse the @a dps_array and update @a r accordingly
+ * Parse the @a dps_array with our decryption policies
+ * and update @a r accordingly
*
* @param[in,out] r recovery information to update
* @param dps_arr serialized data to parse
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
parse_dps_array (struct ANASTASIS_Recovery *r,
- json_t *dps_arr)
+ const json_t *dps_arr)
{
json_t *dps;
- unsigned int n_index;
+ size_t n_index;
if (! json_is_array (dps_arr))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- r->ri.dps_len = json_array_size (dps_arr);
+ if (json_array_size (dps_arr) > UINT_MAX)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ r->ri.dps_len
+ = (unsigned int) json_array_size (dps_arr);
r->dps = GNUNET_new_array (r->ri.dps_len,
struct DecryptionPolicy);
r->ri.dps = GNUNET_new_array (r->ri.dps_len,
@@ -1185,14 +1263,15 @@ parse_dps_array (struct ANASTASIS_Recovery *r,
json_array_foreach (dps_arr, n_index, dps)
{
struct DecryptionPolicy *dp = &r->dps[n_index];
- json_t *challenges;
+ const json_t *challenges;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("emk",
- &dp->emk),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &dp->salt),
- GNUNET_JSON_spec_json ("challenges",
- &challenges),
+ GNUNET_JSON_spec_varsize ("encrypted_master_key",
+ &dp->emk,
+ &dp->emk_size),
+ GNUNET_JSON_spec_fixed_auto ("master_salt",
+ &dp->master_salt),
+ GNUNET_JSON_spec_array_const ("challenges",
+ &challenges),
GNUNET_JSON_spec_end ()
};
const char *err_json_name;
@@ -1213,20 +1292,22 @@ parse_dps_array (struct ANASTASIS_Recovery *r,
JSON_INDENT (2));
return GNUNET_SYSERR;
}
- if (! json_is_array (challenges))
+ GNUNET_assert (NULL != dp->emk);
+ GNUNET_assert (dp->emk_size > 0);
+ if (json_array_size (challenges) > UINT_MAX)
{
GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
- dp->pub_details.challenges_length = json_array_size (challenges);
- dp->pub_details.challenges = GNUNET_new_array (
- dp->pub_details.challenges_length,
- struct ANASTASIS_Challenge *);
+ dp->pub_details.challenges_length
+ = (unsigned int) json_array_size (challenges);
+ dp->pub_details.challenges
+ = GNUNET_new_array (dp->pub_details.challenges_length,
+ struct ANASTASIS_Challenge *);
{
json_t *challenge;
- unsigned int c_index;
+ size_t c_index;
json_array_foreach (challenges, c_index, challenge)
{
struct ANASTASIS_CRYPTO_TruthUUIDP uuid;
@@ -1263,7 +1344,7 @@ parse_dps_array (struct ANASTASIS_Recovery *r,
}
}
}
- GNUNET_JSON_parse_free (spec);
+ /* Do NOT free the spec: we are still using dp->ems. */
}
return GNUNET_OK;
}
@@ -1305,9 +1386,9 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx,
const char *err_json_name;
unsigned int err_line;
uint32_t version;
- json_t *dps_arr;
- json_t *cs_arr;
- json_t *id_data;
+ const json_t *dps_arr;
+ const json_t *cs_arr;
+ const json_t *id_data;
const char *provider_url;
const char *secret_name;
void *ecs;
@@ -1315,20 +1396,21 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("id",
&r->id),
- GNUNET_JSON_spec_string ("provider_url",
+ TALER_JSON_spec_web_url ("provider_url",
&provider_url),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("secret_name",
- &secret_name)),
+ &secret_name),
+ NULL),
GNUNET_JSON_spec_uint32 ("version",
&version),
- GNUNET_JSON_spec_json ("dps",
- &dps_arr),
- GNUNET_JSON_spec_json ("cs",
- &cs_arr),
- GNUNET_JSON_spec_json ("id_data",
- &id_data),
- GNUNET_JSON_spec_varsize ("core_secret",
+ GNUNET_JSON_spec_array_const ("decryption_policies",
+ &dps_arr),
+ GNUNET_JSON_spec_array_const ("challenges",
+ &cs_arr),
+ GNUNET_JSON_spec_object_const ("id_data",
+ &id_data),
+ GNUNET_JSON_spec_varsize ("encrypted_core_secret",
&ecs,
&ecs_size),
GNUNET_JSON_spec_end ()
@@ -1361,7 +1443,7 @@ ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx,
GNUNET_JSON_parse_free (spec);
return NULL;
}
- r->id_data = json_incref (id_data);
+ r->id_data = json_incref ((json_t *) id_data);
r->provider_url = GNUNET_strdup (provider_url);
if (NULL != secret_name)
r->secret_name = GNUNET_strdup (secret_name);
@@ -1428,16 +1510,19 @@ ANASTASIS_recovery_abort (struct ANASTASIS_Recovery *r)
}
GNUNET_free (r->solved_challenges);
for (unsigned int j = 0; j < r->ri.dps_len; j++)
+ {
GNUNET_free (r->dps[j].pub_details.challenges);
+ GNUNET_free (r->dps[j].emk);
+ }
GNUNET_free (r->ri.dps);
for (unsigned int i = 0; i < r->ri.cs_len; i++)
{
- struct ANASTASIS_Challenge *cs = r->ri.cs[i];
+ struct ANASTASIS_Challenge *cs = &r->cs[i];
- if (NULL != cs->kslo)
+ if (NULL != cs->tso)
{
- ANASTASIS_keyshare_lookup_cancel (cs->kslo);
- cs->kslo = NULL;
+ ANASTASIS_truth_solve_cancel (cs->tso);
+ cs->tso = NULL;
}
GNUNET_free (cs->url);
GNUNET_free (cs->type);