[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] branch master updated: split into recovery and backup
From: |
gnunet |
Subject: |
[taler-anastasis] branch master updated: split into recovery and backup |
Date: |
Fri, 05 Feb 2021 11:38:42 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository anastasis.
The following commit(s) were added to refs/heads/master by this push:
new c84456d split into recovery and backup
c84456d is described below
commit c84456d9177d2b5a3636dfdc1dc2c9524c4e9b5b
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Fri Feb 5 11:38:40 2021 +0100
split into recovery and backup
---
src/lib/Makefile.am | 3 +-
src/lib/anastasis.c | 2270 ------------------------------------------
src/lib/anastasis_recovery.c | 1059 ++++++++++++++++++++
3 files changed, 1061 insertions(+), 2271 deletions(-)
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index ec92c34..654f615 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -13,7 +13,8 @@ libanastasis_la_LDFLAGS = \
-version-info 0:0:0 \
-no-undefined
libanastasis_la_SOURCES = \
- anastasis.c
+ anastasis_backup.c \
+ anastasis_recovery.c
libanastasis_la_LIBADD = \
$(top_builddir)/src/util/libanastasisutil.la \
$(top_builddir)/src/restclient/libanastasisrest.la \
diff --git a/src/lib/anastasis.c b/src/lib/anastasis.c
deleted file mode 100644
index e7db6c1..0000000
--- a/src/lib/anastasis.c
+++ /dev/null
@@ -1,2270 +0,0 @@
-/*
- This file is part of Anastasis
- Copyright (C) 2020 Taler Systems SA
-
- 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
- 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
- * @author Christian Grothoff
- * @author Dominik Meister
- * @author Dennis Neufeld
- */
-
-#include "anastasis.h"
-#include <taler/taler_json_lib.h>
-#include <gnunet/gnunet_util_lib.h>
-#include <taler/taler_merchant_service.h>
-
-
-/**
- * stores provider URLs, identity key material, decrypted recovery document
(internally!)
-*/
-struct ANASTASIS_Recovery
-{
- /**
- * Callback to send back a recovery document with the policies and the
version
- */
- ANASTASIS_PolicyCallback pc;
-
- /**
- * closure for the Policy callback
- */
- void *pc_cls;
-
- /**
- * Callback to send back the core secret which was saved by
- * anastasis, after all challenges are completed
- */
- ANASTASIS_CoreSecretCallback csc;
-
- /**
- * Closure for the core secret callback
- */
- void *csc_cls;
-
- /**
- * Identity key material used for the derivation of keys
- */
- struct ANASTASIS_CRYPTO_UserIdentifierP id;
-
- /**
- * Public key for a request
- */
- struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key;
-
- /**
- * Curl context
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * Reference to the policy lookup operation which is executed
- */
- struct ANASTASIS_PolicyLookupOperation *plo;
-
- /**
- * Encrypted recovery document, only used for the description
- */
- void *encrypted_recovery_document;
-
- /**
- * size of the ecrypted recovery document
- */
- size_t enc_rec_doc_size;
-
- /**
- * expected http status
- */
- unsigned int http_status;
-
- /**
- * expected http status
- */
- unsigned int response_code;
-
- /**
- * retrieved encrypted core secret from policy
- */
- void *enc_core_secret;
-
- /**
- * size of the core secret
- */
- size_t enc_core_secret_size;
-
- /**
- * Length of available decryption policies //FIXME: Copy paste?
- */
- struct ANASTASIS_CRYPTO_PowSalt policy_salt;
-
- /**
- * Length of available decryption policies //FIXME: Copy paste?
- */
- struct ANASTASIS_Challenge *solved_challenges;
-
- /**
- * Length of available decryption policies //FIXME: Copy paste?
- */
- unsigned int solved_challenge_pos;
-
- /**
- * Recovery information which is sent to the user
- */
- struct ANASTASIS_RecoveryInformation *ri;
-
- /**
- * Identity data to user id from.
- */
- const json_t *id_data;
-};
-
-
-/**
- * Challenge struct contains the nonce and public key's needed for the
- * recovery process and a reference to ANASTASIS_Recovery.
- */
-struct ANASTASIS_Challenge
-{
- /**
- * Callback which gives back the instructions and a status code of the
request to the user
- */
- ANASTASIS_ChallengeCallback cc;
-
- /**
- * Closure for the challenge callback
- */
- void *cc_cls;
-
- /**
- * Callback which gives back the instructions and a status code of the
request to the user
- */
- ANASTASIS_AnswerFeedback af;
-
- /**
- * Closure for the challenge callback
- */
- void *af_cls;
-
- /**
- * Reference to the recovery process which is ongoing
- */
- struct ANASTASIS_Recovery *recovery;
-
- /**
- * url to the escrow provider for this challenge
- */
- const char *url;
-
- /**
- * truth public key which identifies this challenge
- */
- struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
-
- /**
- * nonce which identifies the challenge
- */
- struct ANASTASIS_CRYPTO_NonceP nonce;
-
- /**
- * Key used to encrypt the truth passed to the server
- */
- struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
-
- /**
- * Salt used to encrypt the truth
- */
- struct ANASTASIS_CRYPTO_PowSalt truth_salt;
-
- /**
- * plaintext challenge which is sent to the client
- */
- void *challenge;
-
- /**
- * size of the challenge
- */
- size_t challenge_size;
-
- /**
- * method of the challenge
- */
- const char *escrow_method;
-
- /**
- * keyshare lookup operation
- */
- struct ANASTASIS_KeyShareLookupOperation *kslo;
-
- /**
- * Curl context
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * Encrypted key share
- */
- struct ANASTASIS_CRYPTO_KeyShareP *key_share;
-
- /**
- * Status of the challenge 0 pending, 1 solved
- */
- unsigned int solved;
-
- /**
- * Expected http status
- */
- unsigned int http_status;
-
- /**
- * Challenge instructions
- */
- const char *instructions;
-
- /**
- * Cost for authentication
- */
- struct TALER_Amount cost;
-
- /**
- * Passes back the payment information for the current challenge
- */
- ANASTASIS_ChallengePaymentCallback cpc;
-
- /**
- * Closure for the payment callback
- */
- void *cpc_cls;
-
- /**
- * The /truth GET operation handle.
- */
- struct ANASTASIS_ChallengeRunOperation *cro;
-
- /**
- * Sends back the status and the instructions of the challenge start
- */
- ANASTASIS_ChallengeStartCallback csc;
-
- /**
- * Closure for the Challenge Start
- */
- void *csc_cls;
-
- /**
- * Payment identifier.
- */
- struct ANASTASIS_PaymentSecretP payment_secret;
-
- /**
- * Payment order ID we got back, if any. Otherwise NULL.
- */
- char *payment_order_id;
-
- /**
- * Payment order ID we are to provide in the request, may be NULL.
- */
- const char *payment_order_req;
-
- bool payment_requested;
-};
-
-
-struct ANASTASIS_ChallengeAnswerOperation
-{
- struct ANASTASIS_Challenge *c;
-};
-
-
-/**
- * Function called with the results of a #ANASTASIS_keyshare_lookup().
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param ud details about the lookup operation
- */
-static void
-keyshare_lookup_cb (void *cls,
- unsigned int http_status,
- const struct ANASTASIS_KeyShareDownloadDetails *dd)
-{
- struct ANASTASIS_Challenge *c = cls;
- c->kslo = NULL;
- if (http_status != c->http_status)
- {
- c->af (c->af_cls,
- http_status,
- TALER_EC_INVALID); // FIXME: Error Code
- return;
- }
- struct ANASTASIS_CRYPTO_UserIdentifierP id;
- ANASTASIS_CRYPTO_user_identifier_derive (c->recovery->id_data,
- &c->truth_salt,
- &id);
- ANASTASIS_CRYPTO_keyshare_decrypt (dd->encrypted_key_share,
- &id,
- &c->key_share);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d decrypted keyshare is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&c->key_share),
- (unsigned long long) sizeof (c->key_share));
-
- c->recovery->solved_challenges[c->recovery->solved_challenge_pos] = *c;
- c->recovery->solved_challenge_pos++;
- c->af (c->af_cls,
- http_status,
- TALER_EC_NONE);
-
- /**
- * 0 equals the challenge was not solved 1 it was solved
- */
- bool missing = true;
- /**
- * Index of the policy which was completed
- */
- unsigned int success = UINT_MAX;
-
- for (unsigned int i = 0; i < c->recovery->ri->dps_len; i++)
- {
- for (unsigned int j = 0; j < c->recovery->ri->dps[i].nonces_length; j++)
- {
- missing = true;
- for (unsigned int k = 0; k < c->recovery->solved_challenge_pos; k++)
- {
- if (0 == memcmp (&c->recovery->ri->dps[i].nonces[j],
- &c->recovery->solved_challenges[k].nonce,
- sizeof(struct ANASTASIS_CRYPTO_NonceP)))
- {
- missing = false;
- break;
- }
- }
- if (missing == true)
- {
- break;
- }
- }
- if (missing == false)
- {
- success = i;
- break;
- }
- }
-
- if (success != UINT_MAX)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d policy was solved \n", __FILE__, __LINE__);
- void *core_secret;
- size_t core_secret_size;
- struct ANASTASIS_CRYPTO_KeyShareP
- key_shares[c->recovery->ri->dps[success].nonces_length];
- struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
- for (unsigned int l = 0; l < c->recovery->ri->dps[success].nonces_length;
- l++)
- {
- for (unsigned int m = 0; m < c->recovery->solved_challenge_pos; m++)
- {
- if (0 == memcmp (&c->recovery->ri->dps[success].nonces[l],
- &c->recovery->solved_challenges[m].nonce,
- sizeof(struct ANASTASIS_CRYPTO_NonceP)))
- {
- key_shares[l] = *c->recovery->solved_challenges[m].key_share;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d keyshare added %s-%llu b at position %x\n",
- __FILE__, __LINE__,
- TALER_B2S (&key_shares[l]),
- (unsigned long long) sizeof (c->key_share),
- l);
- }
- }
- }
- ANASTASIS_CRYPTO_policy_key_derive (key_shares,
- c->recovery->ri->dps[success].
- nonces_length,
- &c->recovery->ri->dps[success].salt,
- &policy_key);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d the policy key is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&policy_key),
- (unsigned long long) sizeof (policy_key));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
- __LINE__,
- TALER_b2s (c->recovery->enc_core_secret,
- c->recovery->enc_core_secret_size),
- (unsigned long long) c->recovery->enc_core_secret_size);
-
- ANASTASIS_CRYPTO_core_secret_recover (&c->recovery->ri->dps[success].emk,
- policy_key,
- c->recovery->enc_core_secret,
- c->recovery->enc_core_secret_size,
- &core_secret,
- &core_secret_size);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__,
- __LINE__,
- TALER_b2s (core_secret,
- core_secret_size),
- (unsigned long long) core_secret_size);
- c->recovery->csc (c->recovery->csc_cls,
- core_secret,
- core_secret_size);
- }
-}
-
-
-/**
- * Cancel a challenge answer operation.
- *
- * @param pso the challenge answer operation to cancel
- */
-void
-ANASTASIS_challenge_answer_cancel (struct
- ANASTASIS_ChallengeAnswerOperation *cao)
-{
- if (NULL != cao->c)
- {
- GNUNET_free (cao->c);
- }
- GNUNET_free (cao);
-}
-
-
-struct ANASTASIS_ChallengeAnswerOperation *
-ANASTASIS_challenge_answer (struct GNUNET_CURL_Context *ctx,
- struct ANASTASIS_Challenge *c,
- const char *answer_str,
- ANASTASIS_AnswerFeedback af,
- void *af_cls)
-{
- struct ANASTASIS_ChallengeAnswerOperation *cao;
-
- cao = GNUNET_new (struct ANASTASIS_ChallengeAnswerOperation);
- cao->c = c;
- c->af = af;
- c->ctx = ctx;
- c->af_cls = af_cls;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d challenge answer is %s\n", __FILE__, __LINE__,
- answer_str);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d challenge %s-%llu is solved with url %s \n", __FILE__,
- __LINE__,
- TALER_B2S (&c->truth_public_key),
- (unsigned long long) sizeof (c->truth_public_key),
- c->url);
-
- c->http_status = MHD_HTTP_OK;
- if (0 == strcmp (c->escrow_method,
- "question"))
- {
- struct GNUNET_HashCode hashed_answer;
- char *str;
-
- GNUNET_CRYPTO_hash (answer_str,
- strlen (answer_str),
- &hashed_answer);
- str = GNUNET_STRINGS_data_to_string_alloc (&hashed_answer,
- sizeof (hashed_answer));
- c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
- c->url,
- &c->truth_public_key,
- &c->truth_key,
- c->payment_requested,
- &c->payment_secret,
- str,
- &keyshare_lookup_cb,
- c);
- GNUNET_free (str);
- if (NULL == c->kslo)
- {
- GNUNET_break (0);
- return NULL;
- }
- }
- else
- {
- c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
- c->url,
- &c->truth_public_key,
- &c->truth_key,
- c->payment_requested,
- &c->payment_secret,
- answer_str,
- &keyshare_lookup_cb,
- c);
- if (NULL == c->kslo)
- {
- GNUNET_break (0);
- return NULL;
- }
- }
- return cao;
-}
-
-
-struct ANASTASIS_ChallengeInformation *
-ANASTASIS_get_challenge (struct ANASTASIS_Challenge *challenge)
-{
- struct ANASTASIS_ChallengeInformation *ci;
-
- ci = GNUNET_new (struct ANASTASIS_ChallengeInformation);
- ci->truth_public_key = &challenge->truth_public_key;
- ci->method = challenge->escrow_method;
- ci->url = challenge->url;
- ci->nonce = &challenge->nonce;
- ci->instructions = challenge->instructions;
- ci->solved = challenge->solved;
- ci->challenge = challenge;
-
- return ci;
-}
-
-
-struct ANASTASIS_Challenge *
-ANASTASIS_json_to_challenge (json_t *challenge)
-{
- GNUNET_assert (json_is_object (challenge));
- const char *challenge_str;
- struct ANASTASIS_Challenge *c = NULL;
-
- challenge_str =
- json_string_value (
- json_object_get (challenge,
- "challenge"));
- GNUNET_assert (GNUNET_OK ==
- GNUNET_STRINGS_string_to_data (
- challenge_str,
- strlen (challenge_str),
- c,
- sizeof (struct ANASTASIS_Challenge)));
- return c;
-}
-
-
-json_t *
-ANASTASIS_challenge_information_to_json (const struct
- ANASTASIS_ChallengeInformation *ci)
-{
- return json_pack ("{s:o,s:s,s:s,s:o,s:s:s:I,s:o}",
- "truth_public_key",
- GNUNET_JSON_from_data_auto (ci->truth_public_key),
- "method",
- ci->method,
- "url",
- ci->url,
- "nonce",
- GNUNET_JSON_from_data_auto (ci->nonce),
- "instructions",
- ci->instructions,
- "solved",
- (json_int_t) ci->solved,
- "challenge",
- GNUNET_JSON_from_data_auto (ci->challenge));
-}
-
-
-/**
- * Function called with the results of a #ANASTASIS_challenge_run().
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param response_string payment request or instructions
- */
-static void
-challenge_run_cb (void *cls,
- unsigned int http_status,
- char *response_string)
-{
- struct ANASTASIS_Challenge *c = cls;
- c->cro = NULL;
-
- if (http_status == MHD_HTTP_PAYMENT_REQUIRED)
- {
- const char *m;
-
- if (0 != strncmp (response_string,
- "taler://pay/http",
- strlen ("taler://pay/http")))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Did not find `%s' in `%s'\n",
- "/-/-/",
- response_string);
- /*FIXME ERROR*/
- return;
- }
- m = strstr (response_string, "/-/-/");
- if (NULL == m)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Did not find `%s' in `%s'\n",
- "/-/-/",
- response_string);
- /*FIXME ERROR*/
-
- /* NOTE: The above is a simplifying assumption for the
- test-logic, hitting this code merely means that
- the assumptions for the test (i.e. no instance) are
- not satisfied, it is not inherently the case that
- the above token must appear in the payment request!
-
- So if you hit this, you might just want to modify
- the code here to handle this better! */
- return;
- }
- c->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Order ID from Anastasis service is `%s'\n",
- c->payment_order_id);
- c->cpc (c->cpc_cls,
- response_string,
- c->url,
- http_status);
- return;
- }
- c->csc (c->csc_cls,
- response_string,
- http_status);
- return;
-}
-
-
-void
-ANASTASIS_challenge_start (struct GNUNET_CURL_Context *ctx,
- struct ANASTASIS_Challenge *c,
- ANASTASIS_ChallengePaymentCallback cpc,
- void *cpc_cls,
- ANASTASIS_ChallengeStartCallback csc,
- void *csc_cls)
-{
- c->ctx = ctx;
- c->csc = csc;
- c->csc_cls = csc_cls;
- c->cpc = cpc;
- c->cpc_cls = cpc_cls;
- c->payment_requested = false;
-
- if (c->payment_order_id != NULL)
- {
- GNUNET_STRINGS_string_to_data (c->payment_order_id,
- strlen (c->payment_order_id),
- &c->payment_secret,
- sizeof (struct
- ANASTASIS_PaymentSecretP));
- c->payment_requested = true;
- }
-
- c->cro = ANASTASIS_challenge_run (c->ctx,
- c->url,
- &c->truth_public_key,
- &c->truth_key,
- c->payment_requested
- ? &c->payment_secret
- : NULL,
- c->payment_requested,
- &challenge_run_cb,
- c);
- if (NULL == c->cro)
- {
- GNUNET_break (0);
- return;
- }
-}
-
-
-/**
- * Function called with the results of a ANASTASIS_policy_lookup
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param ud 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_t *recovery_document;
- json_error_t json_error;
- json_t *dec_policies;
- json_t *esc_methods;
-
- r->response_code = http_status;
- r->ri = GNUNET_new (struct ANASTASIS_RecoveryInformation);
- r->plo = NULL;
- if (http_status != r->http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u in %s:%u\n",
- http_status,
- __FILE__,
- __LINE__);
-
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_INVALID); // FIXME: Error Code
- // r->pc = NULL;
- ANASTASIS_recovery_abort (r);
- return;
- }
- if (NULL == dd->policy)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "No recovery data available");
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_INVALID); // FIXME: Error Code
- // r->pc = NULL;
- ANASTASIS_recovery_abort (r);
- return;
- }
- ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id,
- dd->policy,
- dd->policy_size,
- &plaintext,
- &size_plaintext);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d rec doc after enc is %s \n",
- __FILE__, __LINE__,
- TALER_b2s (plaintext, size_plaintext));
- // FIXME COMPRESSION
-
- recovery_document = json_loadb ((char *) plaintext,
- size_plaintext,
- JSON_DECODE_ANY,
- &json_error);
- GNUNET_free (plaintext);
- if (NULL == recovery_document)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to read JSON input: %s at %d:%s (offset: %d)\n",
- json_error.text,
- json_error.line,
- json_error.source,
- json_error.position);
- GNUNET_break_op (0);
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_INVALID); // FIXME: Error Code
- ANASTASIS_recovery_abort (r);
- return;
- }
-
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("policies",
- &dec_policies),
- GNUNET_JSON_spec_json ("escrow_methods",
- &esc_methods),
- GNUNET_JSON_spec_varsize ("core_secret",
- &r->enc_core_secret,
- &r->enc_core_secret_size),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (recovery_document,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- json_decref (recovery_document);
- recovery_document = NULL;
- GNUNET_JSON_parse_free (spec);
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_INVALID); // FIXME: Error Code
- ANASTASIS_recovery_abort (r);
- return;
- }
- json_decref (recovery_document);
- recovery_document = NULL;
- 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);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
- __LINE__,
- TALER_b2s (r->enc_core_secret,
- r->enc_core_secret_size),
- (unsigned long long) r->enc_core_secret_size);
- r->solved_challenges = GNUNET_new_array (r->ri->cs_len,
- struct ANASTASIS_Challenge);
-
- struct ANASTASIS_Challenge **cs = GNUNET_new_array (r->ri->cs_len,
- struct
ANASTASIS_Challenge
- *);
- for (unsigned int i = 0; i < r->ri->cs_len; i++)
- {
- cs[i] = GNUNET_new (struct ANASTASIS_Challenge);
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("nonce",
- &cs[i]->nonce),
- GNUNET_JSON_spec_string ("url",
- &cs[i]->url),
- GNUNET_JSON_spec_string ("instructions",
- &cs[i]->instructions),
- GNUNET_JSON_spec_fixed_auto ("truth_key",
- &cs[i]->truth_key),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &cs[i]->truth_salt),
- GNUNET_JSON_spec_string ("escrow_method",
- &cs[i]->escrow_method),
- GNUNET_JSON_spec_end ()
- };
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (esc_methods, i),
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- json_decref (esc_methods);
- GNUNET_JSON_parse_free (spec);
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_INVALID); // FIXME: Error Code
- ANASTASIS_recovery_abort (r);
- return;
- }
- ANASTASIS_CRYPTO_truth_public_key_derive (&cs[i]->nonce,
- &cs[i]->truth_public_key);
- cs[i]->recovery = r;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d challenge public key is %s-%llu b\n", __FILE__,
- __LINE__,
- TALER_B2S (&cs[i]->truth_public_key),
- (unsigned long long) sizeof (cs[i]->truth_public_key));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d url is %s\n", __FILE__, __LINE__,
- cs[i]->url);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth key is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&cs[i]->truth_key),
- (unsigned long long) sizeof (cs[i]->truth_key));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth_salt is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&cs[i]->truth_salt),
- (unsigned long long) sizeof (cs[i]->truth_salt));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d escrow method is %s\n", __FILE__, __LINE__,
- cs[i]->escrow_method);
- }
-
- for (unsigned int j = 0; j < r->ri->dps_len; j++)
- {
- size_t n_index;
- json_t *nonces;
- json_t *nonce;
-
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("master_key",
- &r->ri->dps[j].emk),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &r->ri->dps[j].salt),
- GNUNET_JSON_spec_uint32 ("nonces_length",
- &r->ri->dps[j].nonces_length),
- GNUNET_JSON_spec_end ()
- };
- nonces = json_object_get (json_array_get (dec_policies, j),
- "nonces");
- GNUNET_assert (json_is_array (nonces));
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (dec_policies, j),
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- json_decref (dec_policies);
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_INVALID); // FIXME: Error Code
- ANASTASIS_recovery_abort (r);
- return;
- }
-
- r->ri->dps[j].nonces = GNUNET_new_array (r->ri->dps[j].nonces_length,
- struct ANASTASIS_CRYPTO_NonceP);
-
- json_array_foreach (nonces, n_index, nonce)
- {
- const char *nonce_str = json_string_value (nonce);
- GNUNET_STRINGS_string_to_data (nonce_str,
- strlen (nonce_str),
- &r->ri->dps[j].nonces[n_index],
- sizeof (struct ANASTASIS_CRYPTO_NonceP));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d escrow nonce is %s-%llu b\n",
- __FILE__, __LINE__,
- TALER_B2S (&r->ri->dps[j].nonces[n_index]),
- (unsigned long long) sizeof (r->ri->dps[j].nonces[n_index]));
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d encrypted master key is %s-%llu b\n",
- __FILE__, __LINE__,
- TALER_B2S (&r->ri->dps[j].emk),
- (unsigned long long) sizeof (r->ri->dps[j].emk));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d policy salt is %s-%llu b\n",
- __FILE__, __LINE__,
- TALER_B2S (&r->ri->dps[j].salt),
- (unsigned long long) sizeof (r->ri->dps[j].salt));
- }
- r->solved_challenge_pos = 0;
- r->ri->cs = cs;
- // SETUP POLICY CALLBACK
- if (NULL != r->pc)
- {
- r->pc (r->pc_cls,
- r->ri,
- TALER_EC_NONE); // FIXME: Error Code
- // r->pc = NULL;
- }
- json_decref (esc_methods);
- json_decref (dec_policies);
-}
-
-
-/**
-* Starts the recovery process by opening callbacks for the coresecret and a
policy callback. A list of
-* providers is checked for policies and passed back to the client.
-*
-* @param ctx the CURL context used to connect to the backend
-* @param id_data contains the users identity, (user account on providers)
-* @param version defines the version which will be downloaded NULL for latest
version
-* @param anastasis_provider_url NULL terminated list of possible provider urls
-* @param salt the server salt
-* @param pc opens the policy call back which holds the downloaded version and
the policies
-* @param pc_cls closure for callback
-* @param csc core secret callback is opened, with this the core secert is
passed to the client after the authentication
-* @param csc_cls handle for the callback
-*/
-struct ANASTASIS_Recovery *
-ANASTASIS_recovery_begin (struct GNUNET_CURL_Context *ctx,
- const json_t *id_data,
- unsigned int version,
- const char *anastasis_provider_url,
- const struct ANASTASIS_CRYPTO_PowSalt *salt,
- ANASTASIS_PolicyCallback pc,
- void *pc_cls,
- ANASTASIS_CoreSecretCallback csc,
- void *csc_cls)
-{
- struct ANASTASIS_Recovery *r;
-
- r = GNUNET_new (struct ANASTASIS_Recovery);
- r->csc = csc;
- r->csc_cls = csc_cls;
- r->pc = pc;
- r->pc_cls = pc_cls;
- r->ctx = ctx;
- r->id_data = id_data;
- r->http_status = MHD_HTTP_OK;
- ANASTASIS_CRYPTO_user_identifier_derive (id_data,
- salt,
- &r->id);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d user_identfier is %s-%llu b\n",
- __FILE__, __LINE__,
- TALER_B2S (&r->id),
- (unsigned long long) sizeof (r->id));
- ANASTASIS_CRYPTO_account_public_key_derive (&r->id,
- &r->pub_key);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d public key is %s-%llu b\n",
- __FILE__, __LINE__,
- TALER_B2S (&r->pub_key),
- (unsigned long long) sizeof (r->pub_key));
-
- if (version != 0)
- {
- r->plo = ANASTASIS_policy_lookup_version (r->ctx,
- anastasis_provider_url,
- &r->pub_key,
- &policy_lookup_cb,
- r,
- &version);
- if (NULL == r->plo)
- {
- GNUNET_break (0);
- return NULL;
- }
- }
- else
- {
- r->plo = ANASTASIS_policy_lookup (r->ctx,
- anastasis_provider_url,
- &r->pub_key,
- &policy_lookup_cb,
- r);
- if (NULL == r->plo)
- {
- GNUNET_break (0);
- return NULL;
- }
- }
-
- return r;
-}
-
-
-void
-ANASTASIS_recovery_free (struct ANASTASIS_Recovery *r)
-{
- GNUNET_free (r->solved_challenges);
- GNUNET_free (r->encrypted_recovery_document);
- GNUNET_free (r->ri->dps);
- GNUNET_free (r->ri->cs);
- GNUNET_free (r->ri);
- GNUNET_free (r);
-}
-
-
-/**
-* Cancels the recovery process
-* @param r handle to the recovery struct
-*/
-void
-ANASTASIS_recovery_abort (struct ANASTASIS_Recovery *r)
-{
- if (NULL != r->plo)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "policy lookup aborted");
- ANASTASIS_policy_lookup_cancel (r->plo);
- r->plo = NULL;
- }
- ANASTASIS_recovery_free (r);
-}
-
-
-/* Upload api
------------------------------------------------------------------ */
-/**
-* provider_url + nonce
-*/
-struct ANASTASIS_Truth
-{
- /**
- * url to the server
- */
- const char *url;
-
- /**
- * identification of the truth
- */
- struct ANASTASIS_CRYPTO_NonceP nonce;
-
- /**
- * method used for this truth
- */
- const char *method;
-
- /**
- * method used for this truth
- */
- const char *instructions;
-
- /**
- * mime type of the truth
- */
- const char *mime_type;
-
- /**
- * keyshare of this truth, used to generate policy keys
- */
- struct ANASTASIS_CRYPTO_KeyShareP key_share;
-
- /**
- * key used to encrypt this truth
- */
- struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
-
- /**
- * server salt used to derive user identifier
- */
- struct ANASTASIS_CRYPTO_PowSalt salt;
-};
-
-/**
-* Truth Upload struct
-*/
-struct ANASTASIS_TruthUpload
-{
- /**
- * Expected HTTP Status
- */
- unsigned int http_status;
-
- /**
- * CURL Context for the Post Request
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * User identifier used for the keyshare encryption
- */
- struct ANASTASIS_CRYPTO_UserIdentifierP id;
-
- /**
- * Callback which tells the user the payment details for the upload
- */
- ANASTASIS_TruthPaymentCallback tpc;
-
- /**
- * Closure for the payment callback
- */
- void *tpc_cls;
-
- /**
- * Callback which sends back the generated truth object later used to build
the policy
- */
- ANASTASIS_TruthCallback tc;
-
- /**
- * Closure for the Callback
- */
- void *tc_cls;
-
- /**
- * Reference to the Truthstore Operation
- */
- struct ANASTASIS_TruthStoreOperation *tso;
-
- // FIXME: Implement payment for truth upload/keyshare download
- int payment_requested;
-
- const char *paid_order_id;
-};
-
-
-static void
-truth_store_callback (void *cls,
- enum ANASTASIS_ErrorCode ec,
- unsigned int http_status,
- const struct ANASTASIS_UploadDetails *ud)
-{
- struct ANASTASIS_TruthUpload *tu = cls;
- tu->tso = NULL;
-
- if (NULL != ud)
- {
- switch (ud->us)
- {
- case ANASTASIS_US_SUCCESS:
- break;
- case ANASTASIS_US_PAYMENT_REQUIRED:
- {
- struct TALER_MERCHANT_PayUriData pd;
-
- if (GNUNET_OK !=
- TALER_MERCHANT_parse_pay_uri (ud->details.payment_request,
- &pd))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Did not find `%s' in `%s'\n",
- "/-/-/",
- ud->details.payment_request);
- GNUNET_break (0);
- return;
- }
- tu->paid_order_id = GNUNET_strdup (pd.order_id);
- TALER_MERCHANT_parse_pay_uri_free (&pd);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "At %s:%d Order ID from Anastasis service is %s\n",
- __FILE__, __LINE__,
- tu->paid_order_id);
- }
- break;
- case ANASTASIS_US_CONFLICTING_TRUTH:
- {
- GNUNET_break (0);
- return;
- }
- case ANASTASIS_US_HTTP_ERROR:
- break;
- case ANASTASIS_US_CLIENT_ERROR:
- GNUNET_break (0);
- return;
- case ANASTASIS_US_SERVER_ERROR:
- GNUNET_break (0);
- return;
- default:
- GNUNET_break (0);
- return;
- }
- }
- return;
-}
-
-
-/**
-* Uploads a truth object onto a escrow provider
-*
-* @param ctx the CURL context used to connect to the backend
-* @param user_id user identifier derived from user data and backend salt
-* @param method defines the method of the challenge (secure question, sms,
email)
-* @param instructions depending on method! usually only for security
question/answer!
-* @param mime_type format of the challenge
-* @param salt the server salt
-* @param truth_data contains the truth for this challenge i.e. phone number,
email address
-* @param truth_data_size size of the data
-* @param tpc opens a truth payment callback to pay the upload
-* @param tpc_cls closure for the payment callback
-* @param tc opens the truth callback which contains the status of the upload
-* @param tc_cls closure for the callback
-*/
-struct ANASTASIS_TruthUpload *
-ANASTASIS_truth_upload (struct GNUNET_CURL_Context *ctx,
- const struct ANASTASIS_CRYPTO_UserIdentifierP *user_id,
- const char *provider_url,
- const char *method,
- const char *instructions,
- const char *mime_type,
- const struct ANASTASIS_CRYPTO_PowSalt *salt,
- const void *truth_data,
- size_t truth_data_size,
- ANASTASIS_TruthPaymentCallback tpc,
- void *tpc_cls,
- ANASTASIS_TruthCallback tc,
- void *tc_cls)
-{
- // FIXME Challenge
- struct ANASTASIS_TruthUpload *tu;
- struct ANASTASIS_Truth *t;
- // struct SaltState *ss; FIXME unused
- struct ANASTASIS_CRYPTO_EncryptedKeyShareP *encrypted_key_share;
- struct ANASTASIS_CRYPTO_TruthPublicKeyP pub_key;
- void *encrypted_truth;
- size_t encrypted_truth_size;
- json_t *truth;
-
- GNUNET_assert (NULL != user_id);
- GNUNET_assert (NULL != salt);
-
- tu = GNUNET_new (struct ANASTASIS_TruthUpload);
- t = GNUNET_new (struct ANASTASIS_Truth);
- tu->tc_cls = tc_cls;
- tu->tpc_cls = tpc_cls;
- tu->tpc = tpc;
- tu->tc = tc;
- tu->ctx = ctx;
- tu->id = *user_id;
- t->url = provider_url;
- t->method = method;
- t->instructions = instructions;
- t->mime_type = mime_type;
- t->salt = *salt;
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &t->nonce,
- sizeof (struct ANASTASIS_CRYPTO_NonceP));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d nonce is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&t->nonce),
- (unsigned long long) sizeof (t->nonce));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d server salt is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (salt),
- (unsigned long long) sizeof (*salt));
- ANASTASIS_CRYPTO_keyshare_create (&t->key_share);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d keyshare is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&t->key_share),
- (unsigned long long) sizeof (t->key_share));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d user identifier is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&tu->id),
- (unsigned long long) sizeof (tu->id));
- ANASTASIS_CRYPTO_keyshare_encrypt (&t->key_share,
- &tu->id,
- &encrypted_key_share);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d encrypted key share is %s-%llu b\n", __FILE__,
__LINE__,
- TALER_B2S (encrypted_key_share),
- (unsigned long long) sizeof (*encrypted_key_share));
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
- &t->truth_key,
- sizeof (struct ANASTASIS_CRYPTO_TruthKeyP));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth key is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&t->truth_key),
- (unsigned long long) sizeof (t->truth_key));
-
- struct GNUNET_HashCode hashed_answer;
- GNUNET_CRYPTO_hash (truth_data,
- truth_data_size,
- &hashed_answer);
-
- ANASTASIS_CRYPTO_truth_encrypt (&t->truth_key,
- &hashed_answer,
- sizeof(hashed_answer),
- &encrypted_truth,
- &encrypted_truth_size);
-
- truth = json_pack ("{s:o," /* encrypted KeyShare */
- " s:s," /* method */
- " s:o," /* nonce */
- " s:s}", /* truth_mime */
- "keyshare_data", GNUNET_JSON_from_data_auto (
- encrypted_key_share),
- "method", method,
- "encrypted_truth", GNUNET_JSON_from_data (
- encrypted_truth, encrypted_truth_size),
- "truth_mime", mime_type);
- GNUNET_free (encrypted_key_share);
- GNUNET_free (encrypted_truth);
- if (NULL == truth)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- ANASTASIS_CRYPTO_truth_public_key_derive (&t->nonce,
- &pub_key);
- tu->tc = tc;
- tu->tc_cls = tc_cls;
- tu->tso = ANASTASIS_truth_store (tu->ctx,
- t->url,
- &pub_key,
- truth,
- tu->payment_requested,
- tu->paid_order_id,
- &truth_store_callback,
- tu);
- if (NULL == tu->tso)
- {
- GNUNET_break (0);
- return NULL;
- }
- if (NULL != tu->tc)
- {
- tu->tc (tu->tc_cls,
- t);
- tu->tc = NULL;
- }
-
- // FIXME PAYMENT CALLBACK
- return tu;
-}
-
-
-/**
-* Cancels a upload process
-* @param tu handle for the upload
-*/
-void
-ANASTASIS_truth_upload_cancel (struct ANASTASIS_TruthUpload *tu)
-{
- if (NULL != tu->tso)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "truth lookup aborted \n");
- ANASTASIS_truth_store_cancel (tu->tso);
- tu->tso = NULL;
- }
- GNUNET_free (tu);
-}
-
-
-/**
-* Free's the truth object which was allocated
-* @param t object to clean up
-*/
-void
-ANASTASIS_truth_free (struct ANASTASIS_Truth *t)
-{
- GNUNET_free (t);
-}
-
-
-json_t *
-ANASTASIS_truth_to_json (const struct ANASTASIS_Truth *t)
-{
- return json_pack ("{s:s,s:o,s:s,s:s,s:s,s:o,s:o,s:o}",
- "url",
- t->url,
- "nonce",
- GNUNET_JSON_from_data_auto (&t->nonce),
- "method",
- t->method,
- "instructions",
- t->instructions,
- "mime-type",
- t->mime_type,
- "key-share",
- GNUNET_JSON_from_data_auto (&t->key_share),
- "truth-key",
- GNUNET_JSON_from_data_auto (&t->truth_key),
- "salt",
- GNUNET_JSON_from_data_auto (&t->salt));
-}
-
-
-struct ANASTASIS_Truth *
-ANASTASIS_truth_from_json (const json_t *json)
-{
- struct ANASTASIS_Truth *t = GNUNET_new (struct ANASTASIS_Truth);
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("url",
- &t->url),
- GNUNET_JSON_spec_fixed_auto ("nonce",
- &t->nonce),
- GNUNET_JSON_spec_string ("method",
- &t->method),
- GNUNET_JSON_spec_string ("instructions",
- &t->instructions),
- GNUNET_JSON_spec_string ("mime-type",
- &t->mime_type),
- GNUNET_JSON_spec_fixed_auto ("key-share",
- &t->key_share),
- GNUNET_JSON_spec_fixed_auto ("truth-key",
- &t->truth_key),
- GNUNET_JSON_spec_fixed_auto ("salt",
- &t->salt),
- GNUNET_JSON_spec_end ()
- };
- const char *err_name;
- unsigned int err_line;
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- &err_name,
- &err_line))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse truth in line %u (%s)\n",
- err_line,
- err_name);
- return NULL;
- }
- return t;
-}
-
-
-/**
-* Policy object to upload
-*/
-struct ANASTASIS_Policy
-{
- /**
- * Encrypted policy master key
- */
- struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
-
- /**
- * salt used to encrypt the master key
- */
- struct ANASTASIS_CRYPTO_SaltP salt;
-
- /**
- * set of truths inside this policy
- */
- struct ANASTASIS_CRYPTO_NonceP *nonces;
-
- /**
- * length of methods used
- */
- uint32_t nonces_length;
-
- /**
- * array of truths
- */
- const struct ANASTASIS_Truth **truths;
-};
-
-/**
-* Creates a policy with a set of trutht's
-* Creates the policy key with the different key shares from the truths and
encrypts the escrow master key.
-* @param truths array of truths which are stored on different providers
-* @param truths_len amount of truths in this policy
-*/
-struct ANASTASIS_Policy *
-ANASTASIS_policy_create (const struct ANASTASIS_Truth *truths[],
- unsigned int truths_len)
-{
- struct ANASTASIS_Policy *p;
- const struct ANASTASIS_Truth *truth;
- struct ANASTASIS_CRYPTO_KeyShareP key_shares[truths_len];
- struct ANASTASIS_CRYPTO_NonceP nonces[truths_len];
-
- p = GNUNET_new (struct ANASTASIS_Policy);
-
- GNUNET_assert (NULL != *truths);
- GNUNET_assert (truths_len > 0);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth array length is %i\n", __FILE__, __LINE__,
- truths_len);
-
- for (unsigned int i = 0; i < truths_len; i++)
- {
- truth = truths[i];
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (truth),
- (unsigned long long) sizeof (struct ANASTASIS_Truth));
- GNUNET_memcpy (&key_shares[i],
- &truth->key_share,
- sizeof (struct ANASTASIS_CRYPTO_KeyShareP));
- GNUNET_assert (NULL != &key_shares[i]);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d keyshare is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&key_shares[i]),
- (unsigned long long) sizeof (key_shares[i]));
- GNUNET_memcpy (&nonces[i],
- &truth->nonce,
- sizeof(struct ANASTASIS_CRYPTO_NonceP));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d nonce is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&nonces[i]),
- (unsigned long long) sizeof (nonces[i]));
- }
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &p->salt,
- sizeof (struct ANASTASIS_CRYPTO_SaltP));
- ANASTASIS_CRYPTO_policy_key_derive (key_shares,
- truths_len,
- &p->salt,
- &p->policy_key);
- GNUNET_assert (NULL != &p->policy_key);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d policy key is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&p->policy_key),
- (unsigned long long) sizeof (p->policy_key));
- p->truths = GNUNET_malloc (truths_len * sizeof (struct ANASTASIS_Truth *));
- GNUNET_memcpy (p->truths,
- truths,
- truths_len * sizeof (struct ANASTASIS_Truth *));
- p->nonces = GNUNET_malloc (truths_len * sizeof (struct
- ANASTASIS_CRYPTO_NonceP));
- GNUNET_memcpy (p->nonces,
- nonces,
- truths_len * sizeof (struct ANASTASIS_CRYPTO_NonceP));
- p->nonces_length = truths_len;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d policy is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (p),
- (unsigned long long) sizeof (*p));
- return p;
-}
-
-
-/**
-* Destroys a policy object
-* @param p handle for the policy to destroy
-*/
-void
-ANASTASIS_policy_destroy (struct ANASTASIS_Policy *p)
-{
- if (NULL != p->nonces)
- {
- GNUNET_free (p->nonces);
- }
- if (NULL != p->truths)
- {
- GNUNET_free (p->truths);
- }
-
- GNUNET_free (p);
-}
-
-
-struct ANASTASIS_SecretShare;
-
-/**
- * State for a "policy store" CMD.
- */
-struct PolicyStoreState
-{
- /**
- * User identifier used as entropy source for the account public key
- */
- struct ANASTASIS_CRYPTO_UserIdentifierP id;
-
- /**
- * Struct to obtain the salt from the server
- */
- struct SaltState *st;
-
- /**
- * The policy data.
- */
- void *recovery_data;
-
- /**
- * Number of bytes in @e recovery_data
- */
- size_t recovery_data_size;
-
- /**
- * Expected status code.
- */
- unsigned int http_status;
-
- /**
- * Server salt
- */
- const struct ANASTASIS_CRYPTO_PowSalt *server_salt;
-
- /**
- * Status of the transaction
- */
- enum ANASTASIS_ErrorCode ec;
-
- /**
- * Eddsa Publickey.
- */
- struct ANASTASIS_CRYPTO_AccountPublicKeyP anastasis_pub;
-
- /**
- * Eddsa Privatekey.
- */
- struct ANASTASIS_CRYPTO_AccountPrivateKeyP anastasis_priv;
-
- /**
- * Hash of the previous upload (maybe bogus if
- * #ANASTASIS_TESTING_UO_PREV_HASH_WRONG is set in @e uo).
- * Maybe all zeros if there was no previous upload.
- */
- struct GNUNET_HashCode prev_hash;
-
- /**
- * Hash of the current upload.
- */
- struct GNUNET_HashCode curr_hash;
-
- /**
- * The /policy POST operation handle.
- */
- struct ANASTASIS_PolicyStoreOperation *pso;
-
- /**
- * URL of the anastasis backend.
- */
- const char *anastasis_url;
-
- /**
- * Payment identifier.
- */
- struct ANASTASIS_PaymentSecretP payment_secret;
-
- /**
- * Payment order ID we got back, if any. Otherwise NULL.
- */
- char *payment_order_id;
-
- /**
- * Payment order ID we are to provide in the request, may be NULL.
- */
- const char *payment_order_req;
-
- int payment_requested;
-
- /**
- * Previous upload, or NULL for none. Used to calculate what THIS
- * upload is based on.
- */
- const char *prev_upload;
-
- /**
- * reference to SecretShare
- */
- struct ANASTASIS_SecretShare *ss;
-
- /**
- * Callback which gives back the payment details
- */
- ANASTASIS_SharePaymentCallback spc;
-
- /**
- * Closure for the payment callback
- */
- void *spc_cls;
-
- /**
- * Callback which gives back the result of the POST Request
- */
- ANASTASIS_ShareResultCallback src;
-
- /**
- * Closure for the Result Callback
- */
- void *src_cls;
-};
-
-/**
-* Defines a recovery document upload process (recovery document consists of
multiple policies)
-*/
-struct ANASTASIS_SecretShare
-{
- /**
- * Closure for the Result Callback
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * References for the upload states and operations (size of truths passed)
- */
- struct PolicyStoreState **pss;
-
- /**
- * Closure for the Result Callback
- */
- unsigned int pss_length;
-};
-
-
-/**
- * Free the state of a "policy store" CMD, and possibly
- * cancel it if it did not complete.
- *
- * @param cls closure.
- */
-static void
-policy_store_cleanup (void *cls)
-{
- struct PolicyStoreState *pss = cls;
-
- if (NULL != pss->pso)
- {
- ANASTASIS_policy_store_cancel (pss->pso);
- pss->pso = NULL;
- }
- if (NULL != pss->recovery_data)
- GNUNET_free (pss->recovery_data);
- if (NULL != pss->payment_order_id)
- GNUNET_free (pss->payment_order_id);
- GNUNET_free (pss);
-}
-
-
-static void
-policy_store_cb (void *cls,
- enum ANASTASIS_ErrorCode ec,
- unsigned int http_status,
- const struct ANASTASIS_UploadDetails *ud)
-{
- struct PolicyStoreState *pss = cls;
- pss->pso = NULL;
- pss->ec = ec;
- if ((http_status != pss->http_status) &&
- (http_status != MHD_HTTP_PAYMENT_REQUIRED))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d in %s:%u\n",
- http_status,
- (int) ec,
- __FILE__,
- __LINE__);
-
- if (NULL != pss->src)
- {
- pss->src (pss->src_cls,
- &pss->curr_hash,
- pss->anastasis_url,
- ec,
- http_status);
- pss->src = NULL;
- }
- return;
- }
- if (NULL != ud)
- {
- switch (ud->us)
- {
- case ANASTASIS_US_SUCCESS:
- if (0 != GNUNET_memcmp (&pss->curr_hash,
- ud->details.curr_backup_hash))
- {
- GNUNET_break (0);
- return;
- }
- break;
- case ANASTASIS_US_PAYMENT_REQUIRED:
- {
- struct TALER_MERCHANT_PayUriData pd;
-
- if (GNUNET_OK !=
- TALER_MERCHANT_parse_pay_uri (ud->details.payment_request,
- &pd))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Did not find `%s' in `%s'\n",
- "/-/-/",
- ud->details.payment_request);
- GNUNET_break (0);
- return;
- }
- pss->payment_order_id = GNUNET_strdup (pd.order_id);
- TALER_MERCHANT_parse_pay_uri_free (&pd);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "At %s:%d Order ID from Anastasis service is %s\n",
- __FILE__, __LINE__,
- pss->payment_order_id);
- memset (&pss->curr_hash,
- 0,
- sizeof (struct GNUNET_HashCode));
- if (NULL != pss->spc)
- {
- pss->spc (pss->spc_cls,
- ud->details.payment_request,
- pss->anastasis_url,
- ec);
- pss->spc = NULL;
- return;
- }
- }
- case ANASTASIS_US_CONFLICTING_POLICY:
- GNUNET_break (0);
- return;
- case ANASTASIS_US_HTTP_ERROR:
- break;
- case ANASTASIS_US_CLIENT_ERROR:
- GNUNET_break (0);
- return;
- case ANASTASIS_US_SERVER_ERROR:
- GNUNET_break (0);
- return;
- default:
- GNUNET_break (0);
- return;
- }
- if (NULL != pss->src)
- {
- pss->src (pss->src_cls,
- &pss->curr_hash,
- pss->anastasis_url,
- ec,
- http_status);
- pss->src = NULL;
- return;
- }
- }
- GNUNET_break (0);
-}
-
-
-/**
- * Counts the number of different providers
- *
- * @param policies Array of policies
- * @param policies_len Length of array
- * @return number of different providers
- */
-static unsigned int
-ANASTASIS_get_num_urls (const struct ANASTASIS_Policy *policies[],
- unsigned int policies_len)
-{
- unsigned int len = 0;
- unsigned int unique_urls_len = 0;
-
- for (unsigned int i = 0; i < policies_len; i++)
- {
- len += policies[i]->nonces_length;
- }
-
- {
- char *provider[len];
-
- for (unsigned int l = 0; l < policies_len; l++)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d policy is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (policies[l]),
- (unsigned long long) sizeof (struct ANASTASIS_Policy));
-
- for (unsigned int j = 0; j < policies[l]->nonces_length; j++)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (policies[l]->truths[j]),
- (unsigned long long) sizeof (struct ANASTASIS_Truth));
-
- int contains_url = 0;
- if (0 < unique_urls_len)
- {
- for (unsigned int k = 0; k < unique_urls_len; k++)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d provider url from truth is %s\n", __FILE__,
- __LINE__,
- policies[l]->truths[j]->url);
-
- if (NULL != provider[k])
- {
- if (0 ==
- strcmp (policies[l]->truths[j]->url, provider[k]))
- {
- contains_url = 1;
- break;
- }
- }
- }
- }
-
- if (0 == contains_url)
- {
- provider[unique_urls_len] = GNUNET_malloc (sizeof (char)
- * strlen (
- policies[l]->truths[j]->
- url) + 1);
- strcpy (provider[unique_urls_len], policies[l]->truths[j]->url);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d unique provider url is %s\n", __FILE__,
- __LINE__,
- provider[unique_urls_len]);
- unique_urls_len++;
- }
- }
- }
- for (unsigned int i = 0; i < unique_urls_len; i++)
- {
- GNUNET_free (provider[i]);
- }
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d unique_urls_len is %d\n", __FILE__, __LINE__,
- unique_urls_len);
-
- return unique_urls_len;
-}
-
-
-struct ANASTASIS_SecretShare *
-ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
- const json_t *id_data,
- const struct GNUNET_HashCode *last_etag,
- const struct ANASTASIS_Policy *policies[],
- unsigned int policies_len,
- const struct ANASTASIS_PaymentDetails *pds,
- unsigned int pds_len,
- ANASTASIS_SharePaymentCallback spc,
- void *spc_cls,
- ANASTASIS_ShareResultCallback src,
- void *src_cls,
- const void *core_secret,
- size_t core_secret_size)
-{
- struct ANASTASIS_SecretShare *ss;
-
- GNUNET_assert (policies_len > 0);
- unsigned int pss_length = ANASTASIS_get_num_urls (policies,
- policies_len);
- struct PolicyStoreState *pss[pss_length];
- struct ANASTASIS_CRYPTO_EncryptedMasterKeyP
- encrypted_master_keys[policies_len];
- struct ANASTASIS_CRYPTO_PolicyKeyP policy_keys[policies_len];
- void *encrypted_core_secret;
- // Recovery document contains the array decryption policies and the array
escrow methods
- json_t *recovery_document;
- size_t recovery_document_size;
- char *recovery_document_str;
- // json array
- json_t *dec_policies;
- // json array
- json_t *esc_methods;
-
- if (0 == pss_length)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "At %s:%d pss_length is %d!\n", __FILE__, __LINE__,
- pss_length);
- GNUNET_break (0);
- return NULL;
- }
-
- ss = GNUNET_new (struct ANASTASIS_SecretShare);
- for (unsigned int i = 0; i < pss_length; i++)
- {
- pss[i] = GNUNET_new (struct PolicyStoreState);
- pss[i]->ss = ss;
- }
- ss->pss = pss;
- ss->pss_length = pss_length;
- ss->ctx = ctx;
-
- for (unsigned int i = 0; i < policies_len; i++)
- {
- policy_keys[i] = policies[i]->policy_key;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d core secret is %s-%llu b\n", __FILE__, __LINE__,
- TALER_b2s (core_secret,
- core_secret_size),
- (unsigned long long) core_secret_size);
-
- ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys,
- policies_len,
- core_secret,
- core_secret_size,
- &encrypted_core_secret,
- encrypted_master_keys);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
- __LINE__,
- TALER_b2s (encrypted_core_secret,
- core_secret_size),
- (unsigned long long) core_secret_size);
-
- dec_policies = json_array ();
- esc_methods = json_array ();
- int index_pss = 0;
- for (unsigned int k = 0; k < policies_len; k++)
- {
- const struct ANASTASIS_Policy *policy = policies[k];
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d policy is %s\n",
- __FILE__,
- __LINE__,
- TALER_B2S (&policy->policy_key));
-
- json_t *nonces = json_array ();
- for (unsigned int b = 0; b < policy->nonces_length; b++)
- {
- json_array_append (nonces,
- GNUNET_JSON_from_data_auto (&policy->nonces[b]));
- }
-
- if (0 !=
- json_array_append_new (
- dec_policies,
- json_pack ("{s:o," /* encrypted master key */
- " s:o," /* policy nonces */
- " s:o," /* policy salt */
- " s:i}", /* policy nonces length */
- "master_key",
- GNUNET_JSON_from_data_auto (
- &encrypted_master_keys[k]),
- "nonces",
- nonces,
- "salt",
- GNUNET_JSON_from_data_auto (&policy->salt),
- "nonces_length",
- (int) policy->nonces_length)))
- {
- GNUNET_break (0);
- json_decref (dec_policies);
- return NULL;
- }
-
- // FIXME CHALLENGE
- for (unsigned int l = 0; l < policy->nonces_length; l++)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truth is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (policy->truths[l]),
- (unsigned long long) sizeof (struct ANASTASIS_Truth));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d keyshare is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&policy->truths[l]->key_share),
- (unsigned long
- long) sizeof (policy->truths[l]->key_share));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d truthkey is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&policy->truths[l]->truth_key),
- (unsigned long
- long) sizeof (policy->truths[l]->truth_key));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d nonce is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&policy->truths[l]->nonce),
- (unsigned long long) sizeof (policy->truths[l]->nonce));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d server salt is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&policy->truths[l]->salt),
- (unsigned long long) sizeof (policy->truths[l]->salt));
-
- // FIXME: JUST APPEND UNIQUE NONCES!!!
- // creates a json array for saving
- if (0 !=
- json_array_append_new (
- esc_methods,
- json_pack ("{s:o," /* truth nonce */
- " s:s," /* provider url */
- " s:s," /* instructions */
- " s:o," /* truth key */
- " s:o," /* truth salt */
- " s:s}", /* escrow method */
- "nonce",
- GNUNET_JSON_from_data_auto (
- &policy->truths[l]->nonce),
- "url",
- policy->truths[l]->url,
- "instructions",
- policy->truths[l]->instructions,
- "truth_key", GNUNET_JSON_from_data_auto (
- &policy->truths[l]->truth_key),
- "salt", GNUNET_JSON_from_data_auto (
- &policy->truths[l]->salt),
- "escrow_method",
- policy->truths[l]->method)))
- {
- GNUNET_break (0);
- json_decref (esc_methods);
- return NULL;
- }
-
- // prepares policy store operation
- bool contains_url = false;
- for (unsigned int j = 0; j < ss->pss_length; j++)
- {
- if (NULL != ss->pss[j]->anastasis_url)
- {
- if (0 == strcmp (ss->pss[j]->anastasis_url,
- policy->truths[l]->url))
- {
- contains_url = true;
- break;
- }
- }
- }
- if (! contains_url)
- {
- ss->pss[index_pss]->anastasis_url = policy->truths[l]->url;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d anastasis url is %s\n", __FILE__, __LINE__,
- ss->pss[index_pss]->anastasis_url);
- if (NULL != last_etag)
- ss->pss[index_pss]->prev_hash = *last_etag;
- ss->pss[index_pss]->server_salt = &policy->truths[l]->salt;
- if (pds_len > 0)
- {
- for (unsigned int m = 0; 0 < pds_len; m++)
- {
- if (NULL == pds[m].provider_url)
- continue;
- if (0 == strcmp (pds[m].provider_url,
- policy->truths[l]->url))
- {
- ss->pss[index_pss]->payment_secret
- = pds[m].payment_secret;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d Payment-Identifier from PD is: %s\n",
- __FILE__,
- __LINE__,
- TALER_B2S (&pds[m].payment_secret));
- break;
- }
- }
- }
- index_pss++;
- }
- }
- }
-
- recovery_document = json_pack (
- "{s:o," /* decryption policies */
- " s:o," /* escrow methods */
- " s:o}", /* encrypted core secret */
- "policies", dec_policies,
- "escrow_methods", esc_methods,
- "core_secret", GNUNET_JSON_from_data (encrypted_core_secret,
- core_secret_size));
- GNUNET_free (encrypted_core_secret);
- GNUNET_assert (NULL != recovery_document);
-
- // FIXME COMPRESSION
- recovery_document_str = json_dumps (recovery_document,
- JSON_COMPACT | JSON_SORT_KEYS);
- recovery_document_size = strlen (recovery_document_str);
- GNUNET_assert (NULL != recovery_document_str);
- json_decref (recovery_document);
-
- for (unsigned int l = 0; l < ss->pss_length; l++)
- {
- ss->pss[l]->http_status = MHD_HTTP_NO_CONTENT;
-
- ss->pss[l]->spc = spc;
- ss->pss[l]->spc_cls = spc_cls;
- ss->pss[l]->src = src;
- ss->pss[l]->src_cls = src_cls;
-
- ANASTASIS_CRYPTO_user_identifier_derive (id_data,
- ss->pss[l]->server_salt,
- &ss->pss[l]->id);
-
- ANASTASIS_CRYPTO_account_private_key_derive (&ss->pss[l]->id,
- &ss->pss[l]->anastasis_priv);
-
- ANASTASIS_CRYPTO_recovery_document_encrypt (&ss->pss[l]->id,
- recovery_document_str,
- recovery_document_size,
- &ss->pss[l]->recovery_data,
-
&ss->pss[l]->recovery_data_size);
- GNUNET_free (recovery_document_str);
- // hash recovery data
- GNUNET_CRYPTO_hash (ss->pss[l]->recovery_data,
- ss->pss[l]->recovery_data_size,
- &ss->pss[l]->curr_hash);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "At %s:%d current hash is %s-%llu b\n", __FILE__, __LINE__,
- TALER_B2S (&ss->pss[l]->curr_hash),
- (unsigned long long) sizeof (struct GNUNET_HashCode));
-
- ss->pss[l]->pso = ANASTASIS_policy_store (ss->ctx,
- ss->pss[l]->anastasis_url,
- &ss->pss[l]->anastasis_priv,
- ( ( (NULL !=
- ss->pss[l]->prev_upload) &&
- (GNUNET_NO == GNUNET_is_zero
(
- last_etag)) ))
- ? last_etag
- : NULL,
- ss->pss[l]->recovery_data,
- ss->pss[l]->recovery_data_size,
- ss->pss[l]->payment_requested,
- (pds_len > 0)
- ? &ss->pss[l]->payment_secret
- : NULL,
- &policy_store_cb,
- ss->pss[l]);
- if (NULL == ss->pss[l]->pso)
- {
- GNUNET_break (0);
- return NULL;
- }
- }
- return ss;
-}
-
-
-/**
-* Cancels a secret share request
-* @param ss handle to the request
-*/
-void
-ANASTASIS_secret_share_cancel (struct ANASTASIS_SecretShare *ss)
-{
- GNUNET_free (ss);
-}
diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c
new file mode 100644
index 0000000..73cf85d
--- /dev/null
+++ b/src/lib/anastasis_recovery.c
@@ -0,0 +1,1059 @@
+/*
+ This file is part of Anastasis
+ Copyright (C) 2020 Taler Systems SA
+
+ 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
+ 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
+ * @author Christian Grothoff
+ * @author Dominik Meister
+ * @author Dennis Neufeld
+ */
+
+#include "anastasis.h"
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_merchant_service.h>
+
+
+/**
+ * stores provider URLs, identity key material, decrypted recovery document
(internally!)
+*/
+struct ANASTASIS_Recovery
+{
+ /**
+ * Callback to send back a recovery document with the policies and the
version
+ */
+ ANASTASIS_PolicyCallback pc;
+
+ /**
+ * closure for the Policy callback
+ */
+ void *pc_cls;
+
+ /**
+ * Callback to send back the core secret which was saved by
+ * anastasis, after all challenges are completed
+ */
+ ANASTASIS_CoreSecretCallback csc;
+
+ /**
+ * Closure for the core secret callback
+ */
+ void *csc_cls;
+
+ /**
+ * Identity key material used for the derivation of keys
+ */
+ struct ANASTASIS_CRYPTO_UserIdentifierP id;
+
+ /**
+ * Public key for a request
+ */
+ struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key;
+
+ /**
+ * Curl context
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Reference to the policy lookup operation which is executed
+ */
+ struct ANASTASIS_PolicyLookupOperation *plo;
+
+ /**
+ * Encrypted recovery document, only used for the description
+ */
+ void *encrypted_recovery_document;
+
+ /**
+ * size of the ecrypted recovery document
+ */
+ size_t enc_rec_doc_size;
+
+ /**
+ * expected http status
+ */
+ unsigned int http_status;
+
+ /**
+ * expected http status
+ */
+ unsigned int response_code;
+
+ /**
+ * retrieved encrypted core secret from policy
+ */
+ void *enc_core_secret;
+
+ /**
+ * size of the core secret
+ */
+ size_t enc_core_secret_size;
+
+ /**
+ * Length of available decryption policies //FIXME: Copy paste?
+ */
+ struct ANASTASIS_CRYPTO_PowSalt policy_salt;
+
+ /**
+ * Length of available decryption policies //FIXME: Copy paste?
+ */
+ struct ANASTASIS_Challenge *solved_challenges;
+
+ /**
+ * Length of available decryption policies //FIXME: Copy paste?
+ */
+ unsigned int solved_challenge_pos;
+
+ /**
+ * Recovery information which is sent to the user
+ */
+ struct ANASTASIS_RecoveryInformation *ri;
+
+ /**
+ * Identity data to user id from.
+ */
+ const json_t *id_data;
+};
+
+
+/**
+ * Challenge struct contains the nonce and public key's needed for the
+ * recovery process and a reference to ANASTASIS_Recovery.
+ */
+struct ANASTASIS_Challenge
+{
+ /**
+ * Callback which gives back the instructions and a status code of the
request to the user
+ */
+ ANASTASIS_ChallengeCallback cc;
+
+ /**
+ * Closure for the challenge callback
+ */
+ void *cc_cls;
+
+ /**
+ * Callback which gives back the instructions and a status code of the
request to the user
+ */
+ ANASTASIS_AnswerFeedback af;
+
+ /**
+ * Closure for the challenge callback
+ */
+ void *af_cls;
+
+ /**
+ * Reference to the recovery process which is ongoing
+ */
+ struct ANASTASIS_Recovery *recovery;
+
+ /**
+ * url to the escrow provider for this challenge
+ */
+ const char *url;
+
+ /**
+ * truth public key which identifies this challenge
+ */
+ struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
+
+ /**
+ * nonce which identifies the challenge
+ */
+ struct ANASTASIS_CRYPTO_NonceP nonce;
+
+ /**
+ * Key used to encrypt the truth passed to the server
+ */
+ struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
+
+ /**
+ * Salt used to encrypt the truth
+ */
+ struct ANASTASIS_CRYPTO_PowSalt truth_salt;
+
+ /**
+ * plaintext challenge which is sent to the client
+ */
+ void *challenge;
+
+ /**
+ * size of the challenge
+ */
+ size_t challenge_size;
+
+ /**
+ * method of the challenge
+ */
+ const char *escrow_method;
+
+ /**
+ * keyshare lookup operation
+ */
+ struct ANASTASIS_KeyShareLookupOperation *kslo;
+
+ /**
+ * Curl context
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Encrypted key share
+ */
+ struct ANASTASIS_CRYPTO_KeyShareP *key_share;
+
+ /**
+ * Status of the challenge 0 pending, 1 solved
+ */
+ unsigned int solved;
+
+ /**
+ * Expected http status
+ */
+ unsigned int http_status;
+
+ /**
+ * Challenge instructions
+ */
+ const char *instructions;
+
+ /**
+ * Cost for authentication
+ */
+ struct TALER_Amount cost;
+
+ /**
+ * Passes back the payment information for the current challenge
+ */
+ ANASTASIS_ChallengePaymentCallback cpc;
+
+ /**
+ * Closure for the payment callback
+ */
+ void *cpc_cls;
+
+ /**
+ * The /truth GET operation handle.
+ */
+ struct ANASTASIS_ChallengeRunOperation *cro;
+
+ /**
+ * Sends back the status and the instructions of the challenge start
+ */
+ ANASTASIS_ChallengeStartCallback csc;
+
+ /**
+ * Closure for the Challenge Start
+ */
+ void *csc_cls;
+
+ /**
+ * Payment identifier.
+ */
+ struct ANASTASIS_PaymentSecretP payment_secret;
+
+ /**
+ * Payment order ID we got back, if any. Otherwise NULL.
+ */
+ char *payment_order_id;
+
+ /**
+ * Payment order ID we are to provide in the request, may be NULL.
+ */
+ const char *payment_order_req;
+
+ bool payment_requested;
+};
+
+
+struct ANASTASIS_ChallengeAnswerOperation
+{
+ struct ANASTASIS_Challenge *c;
+};
+
+
+/**
+ * Function called with the results of a #ANASTASIS_keyshare_lookup().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param ud details about the lookup operation
+ */
+static void
+keyshare_lookup_cb (void *cls,
+ unsigned int http_status,
+ const struct ANASTASIS_KeyShareDownloadDetails *dd)
+{
+ struct ANASTASIS_Challenge *c = cls;
+ c->kslo = NULL;
+ if (http_status != c->http_status)
+ {
+ c->af (c->af_cls,
+ http_status,
+ TALER_EC_INVALID); // FIXME: Error Code
+ return;
+ }
+ struct ANASTASIS_CRYPTO_UserIdentifierP id;
+ ANASTASIS_CRYPTO_user_identifier_derive (c->recovery->id_data,
+ &c->truth_salt,
+ &id);
+ ANASTASIS_CRYPTO_keyshare_decrypt (dd->encrypted_key_share,
+ &id,
+ &c->key_share);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d decrypted keyshare is %s-%llu b\n", __FILE__, __LINE__,
+ TALER_B2S (&c->key_share),
+ (unsigned long long) sizeof (c->key_share));
+
+ c->recovery->solved_challenges[c->recovery->solved_challenge_pos] = *c;
+ c->recovery->solved_challenge_pos++;
+ c->af (c->af_cls,
+ http_status,
+ TALER_EC_NONE);
+
+ /**
+ * 0 equals the challenge was not solved 1 it was solved
+ */
+ bool missing = true;
+ /**
+ * Index of the policy which was completed
+ */
+ unsigned int success = UINT_MAX;
+
+ for (unsigned int i = 0; i < c->recovery->ri->dps_len; i++)
+ {
+ for (unsigned int j = 0; j < c->recovery->ri->dps[i].nonces_length; j++)
+ {
+ missing = true;
+ for (unsigned int k = 0; k < c->recovery->solved_challenge_pos; k++)
+ {
+ if (0 == memcmp (&c->recovery->ri->dps[i].nonces[j],
+ &c->recovery->solved_challenges[k].nonce,
+ sizeof(struct ANASTASIS_CRYPTO_NonceP)))
+ {
+ missing = false;
+ break;
+ }
+ }
+ if (missing == true)
+ {
+ break;
+ }
+ }
+ if (missing == false)
+ {
+ success = i;
+ break;
+ }
+ }
+
+ if (success != UINT_MAX)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d policy was solved \n", __FILE__, __LINE__);
+ void *core_secret;
+ size_t core_secret_size;
+ struct ANASTASIS_CRYPTO_KeyShareP
+ key_shares[c->recovery->ri->dps[success].nonces_length];
+ struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
+ for (unsigned int l = 0; l < c->recovery->ri->dps[success].nonces_length;
+ l++)
+ {
+ for (unsigned int m = 0; m < c->recovery->solved_challenge_pos; m++)
+ {
+ if (0 == memcmp (&c->recovery->ri->dps[success].nonces[l],
+ &c->recovery->solved_challenges[m].nonce,
+ sizeof(struct ANASTASIS_CRYPTO_NonceP)))
+ {
+ key_shares[l] = *c->recovery->solved_challenges[m].key_share;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d keyshare added %s-%llu b at position %x\n",
+ __FILE__, __LINE__,
+ TALER_B2S (&key_shares[l]),
+ (unsigned long long) sizeof (c->key_share),
+ l);
+ }
+ }
+ }
+ ANASTASIS_CRYPTO_policy_key_derive (key_shares,
+ c->recovery->ri->dps[success].
+ nonces_length,
+ &c->recovery->ri->dps[success].salt,
+ &policy_key);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d the policy key is %s-%llu b\n", __FILE__, __LINE__,
+ TALER_B2S (&policy_key),
+ (unsigned long long) sizeof (policy_key));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
+ __LINE__,
+ TALER_b2s (c->recovery->enc_core_secret,
+ c->recovery->enc_core_secret_size),
+ (unsigned long long) c->recovery->enc_core_secret_size);
+
+ ANASTASIS_CRYPTO_core_secret_recover (&c->recovery->ri->dps[success].emk,
+ policy_key,
+ c->recovery->enc_core_secret,
+ c->recovery->enc_core_secret_size,
+ &core_secret,
+ &core_secret_size);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__,
+ __LINE__,
+ TALER_b2s (core_secret,
+ core_secret_size),
+ (unsigned long long) core_secret_size);
+ c->recovery->csc (c->recovery->csc_cls,
+ core_secret,
+ core_secret_size);
+ }
+}
+
+
+/**
+ * Cancel a challenge answer operation.
+ *
+ * @param pso the challenge answer operation to cancel
+ */
+void
+ANASTASIS_challenge_answer_cancel (struct
+ ANASTASIS_ChallengeAnswerOperation *cao)
+{
+ if (NULL != cao->c)
+ {
+ GNUNET_free (cao->c);
+ }
+ GNUNET_free (cao);
+}
+
+
+struct ANASTASIS_ChallengeAnswerOperation *
+ANASTASIS_challenge_answer (struct GNUNET_CURL_Context *ctx,
+ struct ANASTASIS_Challenge *c,
+ const char *answer_str,
+ ANASTASIS_AnswerFeedback af,
+ void *af_cls)
+{
+ struct ANASTASIS_ChallengeAnswerOperation *cao;
+
+ cao = GNUNET_new (struct ANASTASIS_ChallengeAnswerOperation);
+ cao->c = c;
+ c->af = af;
+ c->ctx = ctx;
+ c->af_cls = af_cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d challenge answer is %s\n", __FILE__, __LINE__,
+ answer_str);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d challenge %s-%llu is solved with url %s \n", __FILE__,
+ __LINE__,
+ TALER_B2S (&c->truth_public_key),
+ (unsigned long long) sizeof (c->truth_public_key),
+ c->url);
+
+ c->http_status = MHD_HTTP_OK;
+ if (0 == strcmp (c->escrow_method,
+ "question"))
+ {
+ struct GNUNET_HashCode hashed_answer;
+ char *str;
+
+ GNUNET_CRYPTO_hash (answer_str,
+ strlen (answer_str),
+ &hashed_answer);
+ str = GNUNET_STRINGS_data_to_string_alloc (&hashed_answer,
+ sizeof (hashed_answer));
+ c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
+ c->url,
+ &c->truth_public_key,
+ &c->truth_key,
+ c->payment_requested,
+ &c->payment_secret,
+ str,
+ &keyshare_lookup_cb,
+ c);
+ GNUNET_free (str);
+ if (NULL == c->kslo)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ }
+ else
+ {
+ c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
+ c->url,
+ &c->truth_public_key,
+ &c->truth_key,
+ c->payment_requested,
+ &c->payment_secret,
+ answer_str,
+ &keyshare_lookup_cb,
+ c);
+ if (NULL == c->kslo)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ }
+ return cao;
+}
+
+
+struct ANASTASIS_ChallengeInformation *
+ANASTASIS_get_challenge (struct ANASTASIS_Challenge *challenge)
+{
+ struct ANASTASIS_ChallengeInformation *ci;
+
+ ci = GNUNET_new (struct ANASTASIS_ChallengeInformation);
+ ci->truth_public_key = &challenge->truth_public_key;
+ ci->method = challenge->escrow_method;
+ ci->url = challenge->url;
+ ci->nonce = &challenge->nonce;
+ ci->instructions = challenge->instructions;
+ ci->solved = challenge->solved;
+ ci->challenge = challenge;
+
+ return ci;
+}
+
+
+struct ANASTASIS_Challenge *
+ANASTASIS_json_to_challenge (json_t *challenge)
+{
+ GNUNET_assert (json_is_object (challenge));
+ const char *challenge_str;
+ struct ANASTASIS_Challenge *c = NULL;
+
+ challenge_str =
+ json_string_value (
+ json_object_get (challenge,
+ "challenge"));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_STRINGS_string_to_data (
+ challenge_str,
+ strlen (challenge_str),
+ c,
+ sizeof (struct ANASTASIS_Challenge)));
+ return c;
+}
+
+
+json_t *
+ANASTASIS_challenge_information_to_json (const struct
+ ANASTASIS_ChallengeInformation *ci)
+{
+ return json_pack ("{s:o,s:s,s:s,s:o,s:s:s:I,s:o}",
+ "truth_public_key",
+ GNUNET_JSON_from_data_auto (ci->truth_public_key),
+ "method",
+ ci->method,
+ "url",
+ ci->url,
+ "nonce",
+ GNUNET_JSON_from_data_auto (ci->nonce),
+ "instructions",
+ ci->instructions,
+ "solved",
+ (json_int_t) ci->solved,
+ "challenge",
+ GNUNET_JSON_from_data_auto (ci->challenge));
+}
+
+
+/**
+ * Function called with the results of a #ANASTASIS_challenge_run().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param response_string payment request or instructions
+ */
+static void
+challenge_run_cb (void *cls,
+ unsigned int http_status,
+ char *response_string)
+{
+ struct ANASTASIS_Challenge *c = cls;
+ c->cro = NULL;
+
+ if (http_status == MHD_HTTP_PAYMENT_REQUIRED)
+ {
+ const char *m;
+
+ if (0 != strncmp (response_string,
+ "taler://pay/http",
+ strlen ("taler://pay/http")))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Did not find `%s' in `%s'\n",
+ "/-/-/",
+ response_string);
+ /*FIXME ERROR*/
+ return;
+ }
+ m = strstr (response_string, "/-/-/");
+ if (NULL == m)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Did not find `%s' in `%s'\n",
+ "/-/-/",
+ response_string);
+ /*FIXME ERROR*/
+
+ /* NOTE: The above is a simplifying assumption for the
+ test-logic, hitting this code merely means that
+ the assumptions for the test (i.e. no instance) are
+ not satisfied, it is not inherently the case that
+ the above token must appear in the payment request!
+
+ So if you hit this, you might just want to modify
+ the code here to handle this better! */
+ return;
+ }
+ c->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Order ID from Anastasis service is `%s'\n",
+ c->payment_order_id);
+ c->cpc (c->cpc_cls,
+ response_string,
+ c->url,
+ http_status);
+ return;
+ }
+ c->csc (c->csc_cls,
+ response_string,
+ http_status);
+ return;
+}
+
+
+void
+ANASTASIS_challenge_start (struct GNUNET_CURL_Context *ctx,
+ struct ANASTASIS_Challenge *c,
+ ANASTASIS_ChallengePaymentCallback cpc,
+ void *cpc_cls,
+ ANASTASIS_ChallengeStartCallback csc,
+ void *csc_cls)
+{
+ c->ctx = ctx;
+ c->csc = csc;
+ c->csc_cls = csc_cls;
+ c->cpc = cpc;
+ c->cpc_cls = cpc_cls;
+ c->payment_requested = false;
+
+ if (c->payment_order_id != NULL)
+ {
+ GNUNET_STRINGS_string_to_data (c->payment_order_id,
+ strlen (c->payment_order_id),
+ &c->payment_secret,
+ sizeof (struct
+ ANASTASIS_PaymentSecretP));
+ c->payment_requested = true;
+ }
+
+ c->cro = ANASTASIS_challenge_run (c->ctx,
+ c->url,
+ &c->truth_public_key,
+ &c->truth_key,
+ c->payment_requested
+ ? &c->payment_secret
+ : NULL,
+ c->payment_requested,
+ &challenge_run_cb,
+ c);
+ if (NULL == c->cro)
+ {
+ GNUNET_break (0);
+ return;
+ }
+}
+
+
+/**
+ * Function called with the results of a ANASTASIS_policy_lookup
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param ud 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_t *recovery_document;
+ json_error_t json_error;
+ json_t *dec_policies;
+ json_t *esc_methods;
+
+ r->response_code = http_status;
+ r->ri = GNUNET_new (struct ANASTASIS_RecoveryInformation);
+ r->plo = NULL;
+ if (http_status != r->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u in %s:%u\n",
+ http_status,
+ __FILE__,
+ __LINE__);
+
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_INVALID); // FIXME: Error Code
+ // r->pc = NULL;
+ ANASTASIS_recovery_abort (r);
+ return;
+ }
+ if (NULL == dd->policy)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No recovery data available");
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_INVALID); // FIXME: Error Code
+ // r->pc = NULL;
+ ANASTASIS_recovery_abort (r);
+ return;
+ }
+ ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id,
+ dd->policy,
+ dd->policy_size,
+ &plaintext,
+ &size_plaintext);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d rec doc after enc is %s \n",
+ __FILE__, __LINE__,
+ TALER_b2s (plaintext, size_plaintext));
+ // FIXME COMPRESSION
+
+ recovery_document = json_loadb ((char *) plaintext,
+ size_plaintext,
+ JSON_DECODE_ANY,
+ &json_error);
+ GNUNET_free (plaintext);
+ if (NULL == recovery_document)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to read JSON input: %s at %d:%s (offset: %d)\n",
+ json_error.text,
+ json_error.line,
+ json_error.source,
+ json_error.position);
+ GNUNET_break_op (0);
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_INVALID); // FIXME: Error Code
+ ANASTASIS_recovery_abort (r);
+ return;
+ }
+
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_json ("policies",
+ &dec_policies),
+ GNUNET_JSON_spec_json ("escrow_methods",
+ &esc_methods),
+ GNUNET_JSON_spec_varsize ("core_secret",
+ &r->enc_core_secret,
+ &r->enc_core_secret_size),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (recovery_document,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ json_decref (recovery_document);
+ recovery_document = NULL;
+ GNUNET_JSON_parse_free (spec);
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_INVALID); // FIXME: Error Code
+ ANASTASIS_recovery_abort (r);
+ return;
+ }
+ json_decref (recovery_document);
+ recovery_document = NULL;
+ 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);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
+ __LINE__,
+ TALER_b2s (r->enc_core_secret,
+ r->enc_core_secret_size),
+ (unsigned long long) r->enc_core_secret_size);
+ r->solved_challenges = GNUNET_new_array (r->ri->cs_len,
+ struct ANASTASIS_Challenge);
+
+ struct ANASTASIS_Challenge **cs = GNUNET_new_array (r->ri->cs_len,
+ struct
ANASTASIS_Challenge
+ *);
+ for (unsigned int i = 0; i < r->ri->cs_len; i++)
+ {
+ cs[i] = GNUNET_new (struct ANASTASIS_Challenge);
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("nonce",
+ &cs[i]->nonce),
+ GNUNET_JSON_spec_string ("url",
+ &cs[i]->url),
+ GNUNET_JSON_spec_string ("instructions",
+ &cs[i]->instructions),
+ GNUNET_JSON_spec_fixed_auto ("truth_key",
+ &cs[i]->truth_key),
+ GNUNET_JSON_spec_fixed_auto ("salt",
+ &cs[i]->truth_salt),
+ GNUNET_JSON_spec_string ("escrow_method",
+ &cs[i]->escrow_method),
+ GNUNET_JSON_spec_end ()
+ };
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json_array_get (esc_methods, i),
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ json_decref (esc_methods);
+ GNUNET_JSON_parse_free (spec);
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_INVALID); // FIXME: Error Code
+ ANASTASIS_recovery_abort (r);
+ return;
+ }
+ ANASTASIS_CRYPTO_truth_public_key_derive (&cs[i]->nonce,
+ &cs[i]->truth_public_key);
+ cs[i]->recovery = r;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d challenge public key is %s-%llu b\n", __FILE__,
+ __LINE__,
+ TALER_B2S (&cs[i]->truth_public_key),
+ (unsigned long long) sizeof (cs[i]->truth_public_key));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d url is %s\n", __FILE__, __LINE__,
+ cs[i]->url);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d truth key is %s-%llu b\n", __FILE__, __LINE__,
+ TALER_B2S (&cs[i]->truth_key),
+ (unsigned long long) sizeof (cs[i]->truth_key));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d truth_salt is %s-%llu b\n", __FILE__, __LINE__,
+ TALER_B2S (&cs[i]->truth_salt),
+ (unsigned long long) sizeof (cs[i]->truth_salt));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d escrow method is %s\n", __FILE__, __LINE__,
+ cs[i]->escrow_method);
+ }
+
+ for (unsigned int j = 0; j < r->ri->dps_len; j++)
+ {
+ size_t n_index;
+ json_t *nonces;
+ json_t *nonce;
+
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("master_key",
+ &r->ri->dps[j].emk),
+ GNUNET_JSON_spec_fixed_auto ("salt",
+ &r->ri->dps[j].salt),
+ GNUNET_JSON_spec_uint32 ("nonces_length",
+ &r->ri->dps[j].nonces_length),
+ GNUNET_JSON_spec_end ()
+ };
+ nonces = json_object_get (json_array_get (dec_policies, j),
+ "nonces");
+ GNUNET_assert (json_is_array (nonces));
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json_array_get (dec_policies, j),
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ json_decref (dec_policies);
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_INVALID); // FIXME: Error Code
+ ANASTASIS_recovery_abort (r);
+ return;
+ }
+
+ r->ri->dps[j].nonces = GNUNET_new_array (r->ri->dps[j].nonces_length,
+ struct ANASTASIS_CRYPTO_NonceP);
+
+ json_array_foreach (nonces, n_index, nonce)
+ {
+ const char *nonce_str = json_string_value (nonce);
+ GNUNET_STRINGS_string_to_data (nonce_str,
+ strlen (nonce_str),
+ &r->ri->dps[j].nonces[n_index],
+ sizeof (struct ANASTASIS_CRYPTO_NonceP));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d escrow nonce is %s-%llu b\n",
+ __FILE__, __LINE__,
+ TALER_B2S (&r->ri->dps[j].nonces[n_index]),
+ (unsigned long long) sizeof (r->ri->dps[j].nonces[n_index]));
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d encrypted master key is %s-%llu b\n",
+ __FILE__, __LINE__,
+ TALER_B2S (&r->ri->dps[j].emk),
+ (unsigned long long) sizeof (r->ri->dps[j].emk));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d policy salt is %s-%llu b\n",
+ __FILE__, __LINE__,
+ TALER_B2S (&r->ri->dps[j].salt),
+ (unsigned long long) sizeof (r->ri->dps[j].salt));
+ }
+ r->solved_challenge_pos = 0;
+ r->ri->cs = cs;
+ // SETUP POLICY CALLBACK
+ if (NULL != r->pc)
+ {
+ r->pc (r->pc_cls,
+ r->ri,
+ TALER_EC_NONE); // FIXME: Error Code
+ // r->pc = NULL;
+ }
+ json_decref (esc_methods);
+ json_decref (dec_policies);
+}
+
+
+/**
+* Starts the recovery process by opening callbacks for the coresecret and a
policy callback. A list of
+* providers is checked for policies and passed back to the client.
+*
+* @param ctx the CURL context used to connect to the backend
+* @param id_data contains the users identity, (user account on providers)
+* @param version defines the version which will be downloaded NULL for latest
version
+* @param anastasis_provider_url NULL terminated list of possible provider urls
+* @param salt the server salt
+* @param pc opens the policy call back which holds the downloaded version and
the policies
+* @param pc_cls closure for callback
+* @param csc core secret callback is opened, with this the core secert is
passed to the client after the authentication
+* @param csc_cls handle for the callback
+*/
+struct ANASTASIS_Recovery *
+ANASTASIS_recovery_begin (struct GNUNET_CURL_Context *ctx,
+ const json_t *id_data,
+ unsigned int version,
+ const char *anastasis_provider_url,
+ const struct ANASTASIS_CRYPTO_PowSalt *salt,
+ ANASTASIS_PolicyCallback pc,
+ void *pc_cls,
+ ANASTASIS_CoreSecretCallback csc,
+ void *csc_cls)
+{
+ struct ANASTASIS_Recovery *r;
+
+ r = GNUNET_new (struct ANASTASIS_Recovery);
+ r->csc = csc;
+ r->csc_cls = csc_cls;
+ r->pc = pc;
+ r->pc_cls = pc_cls;
+ r->ctx = ctx;
+ r->id_data = id_data;
+ r->http_status = MHD_HTTP_OK;
+ ANASTASIS_CRYPTO_user_identifier_derive (id_data,
+ salt,
+ &r->id);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d user_identfier is %s-%llu b\n",
+ __FILE__, __LINE__,
+ TALER_B2S (&r->id),
+ (unsigned long long) sizeof (r->id));
+ ANASTASIS_CRYPTO_account_public_key_derive (&r->id,
+ &r->pub_key);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "At %s:%d public key is %s-%llu b\n",
+ __FILE__, __LINE__,
+ TALER_B2S (&r->pub_key),
+ (unsigned long long) sizeof (r->pub_key));
+
+ if (version != 0)
+ {
+ r->plo = ANASTASIS_policy_lookup_version (r->ctx,
+ anastasis_provider_url,
+ &r->pub_key,
+ &policy_lookup_cb,
+ r,
+ &version);
+ if (NULL == r->plo)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ }
+ else
+ {
+ r->plo = ANASTASIS_policy_lookup (r->ctx,
+ anastasis_provider_url,
+ &r->pub_key,
+ &policy_lookup_cb,
+ r);
+ if (NULL == r->plo)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ }
+
+ return r;
+}
+
+
+void
+ANASTASIS_recovery_free (struct ANASTASIS_Recovery *r)
+{
+ GNUNET_free (r->solved_challenges);
+ GNUNET_free (r->encrypted_recovery_document);
+ GNUNET_free (r->ri->dps);
+ GNUNET_free (r->ri->cs);
+ GNUNET_free (r->ri);
+ GNUNET_free (r);
+}
+
+
+/**
+* Cancels the recovery process
+* @param r handle to the recovery struct
+*/
+void
+ANASTASIS_recovery_abort (struct ANASTASIS_Recovery *r)
+{
+ if (NULL != r->plo)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "policy lookup aborted");
+ ANASTASIS_policy_lookup_cancel (r->plo);
+ r->plo = NULL;
+ }
+ ANASTASIS_recovery_free (r);
+}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-anastasis] branch master updated: split into recovery and backup,
gnunet <=