summaryrefslogtreecommitdiff
path: root/src/lib/anastasis_recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/anastasis_recovery.c')
-rw-r--r--src/lib/anastasis_recovery.c618
1 files changed, 331 insertions, 287 deletions
diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c
index ac10418..f164c93 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->kslo)
+ 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->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),
@@ -752,10 +797,9 @@ policy_lookup_cb (void *cls,
r->ri.secret_name = r->secret_name;
}
}
- json_decref (recovery_document);
}
- r->ri.version = dd->version;
+ r->ri.version = dd->details.ok.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,
@@ -777,14 +821,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,13 +845,12 @@ 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);
+ json_decref (recovery_document);
return;
}
cs->url = GNUNET_strdup (url);
@@ -817,43 +860,44 @@ 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);
+ json_decref (recovery_document);
return;
}
+ GNUNET_assert (NULL != dp->emk);
+ GNUNET_assert (dp->emk_size > 0);
+
dp->pub_details.challenges_length = json_array_size (uuids);
dp->pub_details.challenges
= GNUNET_new_array (dp->pub_details.challenges_length,
@@ -873,13 +917,12 @@ 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);
+ json_decref (recovery_document);
return;
}
for (unsigned int i = 0; i<r->ri.cs_len; i++)
@@ -895,21 +938,19 @@ 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);
+ json_decref (recovery_document);
return;
}
}
- json_decref (uuids);
}
- json_decref (dec_policies);
r->pc (r->pc_cls,
&r->ri);
+ json_decref (recovery_document);
}
@@ -997,11 +1038,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 +1061,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 +1093,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,22 +1106,24 @@ 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;
@@ -1099,27 +1146,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,34 +1189,27 @@ 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;
@@ -1185,14 +1228,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,12 +1257,8 @@ parse_dps_array (struct ANASTASIS_Recovery *r,
JSON_INDENT (2));
return GNUNET_SYSERR;
}
- if (! json_is_array (challenges))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
+ GNUNET_assert (NULL != dp->emk);
+ GNUNET_assert (dp->emk_size > 0);
dp->pub_details.challenges_length = json_array_size (challenges);
dp->pub_details.challenges = GNUNET_new_array (
dp->pub_details.challenges_length,
@@ -1263,7 +1303,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 +1345,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 +1355,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 +1402,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 +1469,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);